Я только начал изучать классы и объекты в Python, и я пришел к следующей проблеме
Кажется, он не работает с переменной n в методах, которые я определил в некоторых случаях:
Например:
def play(self):
if n < 4:
n += 1
self.mood = moods[n]
else:
self.mood = self.mood
это вызывает и ошибку, что n не определено в строке «if n <4:», но если я стираю эту часть, «n + = 1» ошибка не появляется. Но даже после этого он, похоже, не обновляет переменную n, если я использую ее в методе:
def new_mood(self):
n = random.randint(0,2)
self.mood = moods[n]
Мне здесь не хватает фундаментальных знаний?
import random
moods = ['terrible',
'bad',
'neutral',
'good',
'great']
n = random.randint(0,2)
class animals:
def __init__(self, species, name, mood):
self.species = species
self.name = name
self.mood = mood
def default_mood(self):
self.mood = moods[2]
def new_mood(self):
n = random.randint(0,2)
self.mood = moods[n]
def play(self):
if n < 4:
n += 1
self.mood = moods[n]
else:
self.mood = self.mood
Max = animals('Dog', 'Max', moods[n])
Princess = animals('Cat', 'Princess', moods[n])
print(Max.name + ' mood is ' + Max.mood)
print(Princess.name + ' mood is ' + Princess.mood)
Max.new_mood()
Max.play()
Princess.play()
print(Max.name + ' mood is ' + Max.mood)
print(Princess.name + ' mood is ' + Princess.mood)
print(Max.mood)
print(Max.name + ' mood is ' + Max.mood)
print(Princess.name + ' mood is ' + Princess.mood)
@brunodesthuilliers, как так? n
- это глобальная переменная, которую они пытаются изменить, не так ли?
@UnholySheep, это не так - то, что хочет OP, также может быть атрибутом экземпляра.
@Marek, вы уверены, что хотите здесь глобальную переменную? Действительно ли настроение одного экземпляра animal
должно зависеть от предыдущих вызовов new_mood()
и / или play()
на экземпляре любойanimal
?
TL; DR: это вызвано не классами, а тем, как область видимости работает в Python. Любое присвоение имени делает это имя локальной переменной, затеняя любые глобальные переменные с таким же именем.
Используйте global
или nonlocal
для явной ссылки на имена из глобальной или содержащей области. Используйте атрибуты класса для ссылки на имена из области действия класса.
Рассмотрим этот минимальный пример без класса:
>>> n = 5
...
>>> def foo():
... if n < 10:
... n += 1
...
>>> foo()
UnboundLocalError: local variable 'n' referenced before assignment
Обратите внимание, как в ошибке написано местный variable? 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]
Есть несколько путей для использования атрибутов класса, в зависимости от того, как нужно обрабатывать изменение и создание подклассов.
повторно открыт, потому что предложенный дубликат здесь не имеет смысла - оператору явно не нужен глобальный.