почему python не может получить доступ к значению глобальной переменной при изменении имени параметра функции?

#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