#python #scope #frame #symbol-table
#python #область действия #фрейм #таблица символов
Вопрос:
почему в этих двух фрагментах кода второй выдает ошибку о назначении локальной переменной? два кода похожи, просто параметры функции разные, во втором он может считывать глобальную переменную, почему не в первом, что меняется при изменении имени параметра в таблице символов?
первый:
def a(z):
z =1
z=3
a(z)
второй:
def a(z):
b = 1
b = 5
a(b)
Комментарии:
1. В первом случае вы обновляете только локальную переменную
z
, которая была параметром функции. Во втором случае такой локальной переменной нет, поэтому вы получаете сообщение об ошибке. Ни один из них не обновляет глобальную переменную.2. В первом случае
z =1
увеличивается параметр z, переданный в функцию. Переменная z уровня модуля не имеет значения. Во втором случае вы пытаетесь увеличить переменную b, однако переменная b не была объявлена в функции и не имеет значения. Следовательно, вы получаете сообщение об ошибке.3. Вам нужно понять несколько понятий, таких как переменная / ссылка, область видимости и объявление / определение.
Ответ №1:
Здесь не используются какие-либо глобальные переменные.
В первом примере z
это параметр функции, а не глобальный. Обратите внимание, что при увеличении z
оно не изменяется в области вызова, потому z
что внутренняя часть функции является копией той z
, которую вы передали извне функции.
Во втором примере внутри функции нет b
(параметр есть z
), поэтому вы получаете ошибку внутри функции при попытке ее изменить.
Чтобы сделать то, что вы пытаетесь сделать, вы должны сделать параметр изменяемым объектом, который содержит значение, которое вы пытаетесь изменить; таким образом, вы можете изменить значение внутри функции, и вызывающий объект получит доступ к новому значению. Вы могли бы определить класс для этой цели, или вы могли бы просто сделать его списком из одного элемента:
def a(z):
z[0] = 1
b = [5]
a(b) # b == [6]
Или, если возможно, лучший подход IMO заключается в том, чтобы не зависеть от изменчивости, а просто возвращать новое значение, требуя, чтобы вызывающий объект явно переназначил его в пределах своей области:
def a(z)
return z 1
b = 5
b = a(b) # b == 6
Комментарии:
1. да, спасибо, я просто пытался понять, почему в первом фрагменте внутренняя функция z может получить копию глобальной области видимости, но не может этого сделать во втором коде внутри функции, где b не может получить копию переменной b глобальной области видимости, как вы упомянулипроблема не в параметре для функции, если я ошибаюсь, пожалуйста, поправьте меня. Спасибо
2. Важно то, что в первом фрагменте
z
внутри функции нет глобальной области действия.
Ответ №2:
Вы должны рассматривать def
блоки как самостоятельные.
В первом фрагменте:
def a(z):
z =1
Что такое z
? Это первый параметр a
Во втором фрагменте:
def a(z):
b = 1
Что такое b
? Неизвестно. Вот почему этот код завершается ошибкой.
Вы также должны заметить, что в вашем первом фрагменте z
внутри функции не то же самое, что z=3
:
>>> def a(z):
... z =1
...
>>> z=3
>>> a(z)
>>>
>>> z
3
Комментарии:
1. да, я просто подумал, почему параметр внутри функции не имеет доступа к значению глобальной переменной, поэтому я не понял эту логику в отношении того, как была разработана таблица символов или написан интерпретатор, что это зависит от того, чтобы параметр внутри функции имел то же имя, что и глобальный, чтобыпервый фрагмент будет эффективным или получит доступ к значению глобальной переменной области видимости
Ответ №3:
Во втором коде параметр равен «z», и вы пытались получить доступ к этому параметру с помощью «b»
def a(z):
b = 1