Переменные внутри и снаружи методов объекта - PullRequest
0 голосов
/ 10 сентября 2018

Я только начал изучать классы и объекты в Python, и я пришел к следующей проблеме

Кажется, он не работает с переменной n в методах, которые я определил в некоторых случаях:

например:

def play(self):
    if n < 4:
        n += 1
        self.mood = moods[n]
    else:
        self.mood = self.mood

это выдает и ошибка, что n не определено в строке "если n <4:", но если я удалю эту часть, "n + = 1" ошибка не появляется. Но даже после этого он не обновляет переменную n, если я использую ее в методе: </p>

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)

1 Ответ

0 голосов
/ 10 сентября 2018

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]  

Существует несколько способов использовать атрибуты класса, в зависимости от того, как нужно обрабатывать изменения и подклассы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...