2016-12-26 6 views
0

Этот скрипт определяет переменную внутри main(), но переменная недоступна func(), которая проходит внутри main(). Почему это?Переменная недоступна для подфункции

#!/usr/bin/env python3 
# vars_in_func.py 
# Test script for variables within a function. 

def func(): 
    print(greeting) 

def main(): 
    greeting = "Hello world" 
    func() 

main() 

Ошибка:

Traceback (most recent call last): 
    File "./vars_in_func.py", line 11, in <module> 
    main() 
    File "./vars_in_func.py", line 9, in main 
    func() 
    File "./vars_in_func.py", line 5, in func 
    print(greeting) 
NameError: name 'greeting' is not defined 

Если преобразовать сценарий python2, ошибка такая же, за исключением того, что говорит global name вместо name.

Я предполагаю, что у меня просто отсутствует ключевое понятие. Я только начал изучать Python после изучения Bash.

Редактировать: После прочтения ответов, я понял свою ошибку: я все еще думать в терминах Bash, где функция либо выполняться в той же оболочке, что и вызывающий (с тем же переменным), или подоболочками вызывающий (унаследованные переменные).

+2

Подробнее о [scope rules] (http://stackoverflow.com/questions/291978/short-description-of-scoping-rules) – trincot

+2

'func' не запускается внутри' main() '. Это просто называется 'main'. Это не значит, что он видит локальные переменные в 'main'. – BrenBarn

ответ

3
greeting = None 

def func(): 
    print(greeting) 

def main(): 
    global greeting 
    greeting = "Hello world" 
    func() 

main() 

В вашем решении приветствие, определенное в основной функции, является локальной переменной и к ней нельзя получить доступ за пределами основной функции. это причина, по которой это давало вам ошибки

+0

Можете ли вы пояснить, почему вам нужно отметить приветствие как глобальное внутри основного метода? Опущение это приведет к некоторому плохому моджо. – Irisshpunk

+0

'приветствие 'помечается как глобальное в функции' main() ', потому что оно * изменено * там. Он не отмечен глобальным в функции 'func()', потому что он * не изменен * там, просто ссылается. Очистить? –

0

В функции python функции не могут получить доступ к любой переменной вне функции, если только ее параметр или не объявлен global.

Это следует надеяться решить проблему:

greeting = None 

def func(): 
    print(greeting) 

def main(): 
    global greeting # Declaring as global means func() can access it 
    greeting = "Hello world" 
    func() 

main() 
+0

Это не совсем так. Функция может * получать доступ к глобальным переменным, но не может * назначать * им, если они не объявлены «глобальными» в пределах области действия. – ekhumoro

2

Я не знаю много о питоне, но в целом глобальные переменные должны быть определены вне рамок основной, но до функции, которую вы хотите использовать их в Если вы не хотите создавать переменную global, вам нужно передать переменную в функцию в качестве параметра.

0

См. this post.

В Python каждая функция имеет свой собственный объем, поэтому вы не можете получить доступ к переменной «приветствия» вне функции «main», так как она определена внутри этой функции.

1

Есть много ответов о правилах обзора python, и это действительно имеет значение здесь. Но, как я вижу ваш вопрос, ваше недоразумение состоит в чем-то совершенно другом: огромная разница между определяющей функцией и ее вызовом.

правило LEGB важно, но то, что действительно имеет значение здесь: «Область применения определяется статический, они выглядели динамически» . Грубо говоря, функция знает, где искать переменную (при компиляции), но она не знает значения переменных (до вызова функции).

В вашем случае вы просто вызываете одну функцию в тело другой функции. Когда вы вызываете функцию, вызывающий передает управление вызываемому абоненту (грубо говоря, представьте, что это как переход в исходный код к началу кода кода функции). Поэтому, когда вы звоните func, вы прыгаете в func тело. Эта функция пытается найти имена: print и greeting (этот процесс называется Name resolution) она выглядит в local объеме, то в global сферы (сферы, где она была определена, не называется) и, наконец, в builtins.Он находит только print в builtins. Поскольку имя greeting не найдено, возникает исключение NameError (исключение возникает в точке, где обнаружена ошибка) в вашем случае в том месте, где main называется func. И когда исключение вообще не обрабатывается, интерпретатор завершает выполнение программы или возвращается в свой интерактивный основной цикл. В любом случае он печатает обратную трассировку стека, за исключением случаев, когда исключение составляет SystemExit.

Надеюсь, что это прояснит некоторые моменты для вас. более

Одно место для поиска информации: The Python Language Reference: Execution model

p.s .: global scope всегда module (файл с кодом), где была определена функция. Очень важно понять !!!

Смежные вопросы