【问题标题】:Variables inside and outside of object methods对象方法内部和外部的变量
【发布时间】:2019-02-14 16:32:35
【问题描述】:

我刚刚开始学习 Python 中的类和对象,我遇到了以下问题

在某些情况下我定义的方法中似乎不适用于变量 n:

例如:

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

这会引发错误,即 n 未在“if 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 实例的情绪真的应该依赖于之前在any animal 实例上对new_mood() 和/或play() 的调用吗?

标签: python class object variables methods


【解决方案1】:

TLDR:这不是由类引起的,而是由 Python 中作用域的工作方式引起的。对名称的任何赋值都会使该名称成为局部变量,从而隐藏任何同名的全局变量。

使用globalnonlocal 从全局或包含范围显式引用名称。使用类属性来引用类范围内的名称。


考虑这个没有类的最小示例:

>>> n = 5
...
>>> def foo():
...    if n < 10:
...        n += 1
...
>>> foo()
UnboundLocalError: local variable 'n' referenced before assignment

注意错误是如何表示 local 变量的? n 里面的foo 不是全局的n!由于本地n 在分配之前不会初始化,因此不能在事先比较中使用它。如果全局 n 不存在,您会得到,并且可能也期望得到同样的错误。

每当在范围内分配名称时,都会自动使该名称成为该范围的本地名称。请注意,这会影响整个范围 - 包括分配之前的事件。如果你只做一个赋值,那只会改变本地名称——它在作用域的末尾被丢弃。

如果你想在外部范围内修改一个名字,你必须告诉 Python。 globalnonlocal 关键字为此存在:

>>> 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]  

several ways 使用类属性,这取决于一个人想要如何处理修改和子类化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 1970-01-01
    相关资源
    最近更新 更多