python - 在Python中如何处理可变类属性

标签 python

我正在执行以下 Python 代码:

class Pet :
    kind = 'dog'    # class variable shared by all instances
    tricks = []

    def __init__(self, name) :
        self.name = name # instance variable unique to each instance
    def changePet(self, newPet) :
        self.kind = newPet
    def addTricks(self, tricks) :
        self.tricks.append(tricks)

pet1 = Pet('mypet')
pet2 = Pet('yourpet')
print 'pet1 kind ::: ', pet1.kind;print 'pet2 kind ::: ', pet2.kind
print 'pet1 name ::: ', pet1.name;print 'pet2 name ::: ', pet2.name

Pet.kind = 'cat'
print 'changed Pet.kind to cat'
print 'pet1 kind ::: ', pet1.kind;print 'pet2 kind ::: ', pet2.kind

#changing pet#1 kind does not change pet#2 kind
pet1.changePet('parrot')
print 'changed pet1.kind to parrot'
print 'pet1 kind ::: ', pet1.kind;print 'pet2 kind ::: ', pet2.kind

pet1.addTricks('imitate')
pet2.addTricks('roll over')
print 'pet1 tricks ::: ', pet1.tricks;print 'pet2 tricks ::: ', pet2.tricks

print Pet.__dict__
print pet1.__dict__
print pet2.__dict__

输出是按照我在互联网上找到的解释。输出结果如下

pet1 kind :::  dog
pet2 kind :::  dog
pet1 name :::  mypet
pet2 name :::  yourpet
changed Pet.kind to cat
pet1 kind :::  cat
pet2 kind :::  cat
changed pet1.kind to parrot
pet1 kind :::  parrot
pet2 kind :::  cat
pet1 tricks :::  ['imitate', 'roll over']
pet2 tricks :::  ['imitate', 'roll over']
{'__module__': '__main__', 'tricks': ['imitate', 'roll over'], 'kind': 'cat', 'addTricks': <function addTricks at 0xb71fa6bc>, 'changePet': <function changePet at 0xb71fa33c>, '__doc__': None, '__init__': <function __init__ at 0xb71fa144>}
{'kind': 'parrot', 'name': 'mypet'}
{'name': 'yourpet'}

现在我的疑问是,为什么可变类对象的处理方式与非可变类对象不同

最佳答案

我不确定他们的待遇是否不同。您只是对它们执行不同的操作。

changePet 的情况下,您将之前未定义的 self.kind 分配给一个值。现在,当 python 尝试查找 pet1.kind 时,它会立即找到它。当查找pet2.kind时,它没有找到它。但是,它确实找到了 Pet.kind,因此它返回了该值。

addTricks而言,您正在尝试改变self.tricks。由于它不存在,因此您会获得对 Pet.tricks 的引用。因此,当您在 self.tricks 上调用 append() 时,您实际上是调用 Pet.tricks.append() 而不是 self.tricks.append().

为了澄清事情,这个:

def changePet(self, newPet) :
    self.kind = newPet
def addTricks(self, tricks) :
    self.tricks.append(tricks)

实际上相当于:

def changePet(self, newPet) :
    self.kind = newPet
def addTricks(self, tricks) :
    Pet.tricks.append(tricks)

为了证明 python 对待可变对象与非可变对象没有区别,我们需要更改您的方法,以便它们执行类似的操作:

def changePet(self, newPet) :
    self.kind = newPet

def addTricks(self, tricks):
    # assign self.tricks to a new value where we previously only mutated it!
    # note: list(self.tricks) returns a copy
    self.tricks = list(self.tricks)
    self.tricks.append(tricks)

现在,当我们再次运行您的代码时,我们会得到以下输出:

pet1 kind :::  dog
pet2 kind :::  dog
pet1 name :::  mypet
pet2 name :::  yourpet
changed Pet.kind to cat
pet1 kind :::  cat
pet2 kind :::  cat
changed pet1.kind to parrot
pet1 kind :::  parrot
pet2 kind :::  cat
pet1 tricks :::  ['imitate']
pet2 tricks :::  ['roll over']
{'__module__': '__main__', 'tricks': [], 'kind': 'cat', 'addTricks': <function addTricks at 0x02A33C30>, 'changePet': <function changePet at 0x02A33BF0>, '__doc__': None, '__init__': <function __init__ at 0x02A33BB0>}
{'tricks': ['imitate'], 'kind': 'parrot', 'name': 'mypet'}
{'tricks': ['roll over'], 'name': 'yourpet'}

关于python - 在Python中如何处理可变类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30138430/

相关文章:

python - 导入到 postgres(python 脚本)时如何进行列划分?

python 创建签名 X509

python - WIndows:创建新控制台窗口的子进程,丢失标准输入/输出

python - 为什么我只能使用一次查询结果?

python - Matplotlib 无法在 Django 上渲染多个等高线图

python - 在python中,当我取钱然后存钱时如何更新余额?

python - 无法在 VirtualBox 共享文件夹上安装 Plone,因为 Python 安装失败

python 的基本元类 : a pure-python analogue?

python - 带有服务帐户的 Google Cloud Pub Sub

python - Django:显示Person模型的属性