TLDR: это вызвано не классами, а тем, как работает область видимости в Python. Любое присвоение имени делает это имя локальной переменной, скрывая любые глобальные переменные с тем же именем.
Используйте global
или nonlocal
, чтобы явно ссылаться на имена из глобальной или содержащей области. Используйте атрибуты класса для ссылки на имена из области видимости класса.
Рассмотрим этот минимальный пример без класса:
>>> n = 5
...
>>> def foo():
... if n < 10:
... n += 1
...
>>> foo()
UnboundLocalError: local variable 'n' referenced before assignment
Обратите внимание, как ошибка говорит локальная переменная? n
внутри foo
не является глобальным n
! Поскольку локальный n
не инициализируется до его присвоения, его нельзя использовать в сравнении заранее. Вы получите, и, вероятно, также ожидаете, такую же ошибку, если глобальный n
не существует.
Всякий раз, когда имя назначается в области, это автоматически делает это имя локальным для этой области. Обратите внимание, что это влияет на всю область, включая вхождения до назначения. Если вы делаете только присвоение, это только меняет локальное имя, которое выбрасывается в конце области.
Если вы хотите изменить имя во внешней области видимости, вы должны указать Python. Для этого существуют ключевые слова global
и nonlocal
:
>>> def foo():
... global n # n refers to the global name n for the entire scope
... if n < 10: # works, we compare against the global n
... n += 1 # modifies the global n, no introduction of local n
Связанные, но немного отличающиеся варианты использования - это переменные, специфичные для класса. Например, n
может быть свойством всех animals
без , затрагивая, скажем, все humans
.
Такие атрибуты класса определены в теле класса. Вы можете ссылаться на них по имени класса, подобно тому, как вы выбираете метод:
class Animals:
n = 0
def new_mood(self):
# we want the 'n' of Animals
Animals.n = random.randint(0,2)
self.mood = moods[Animals.n]
Существует несколько способов использовать атрибуты класса, в зависимости от того, как нужно обрабатывать изменения и подклассы.