为什么Python作用域对于list变量和string变量的行为似乎不同?

2024-09-22 20:35:19 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有以下Python代码:

import sys

class DogStr:
    tricks = ''

    def add_trick(self, trick):
        self.tricks = trick

class DogList:
    tricks = []

    def add_trick(self, trick):
        self.tricks.append(trick)

# Dealing with DogStr
d = DogStr()
e = DogStr()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)

# Dealing with DogList
d = DogList()
e = DogList()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)

使用Python 3.6.5运行此代码,我得到以下输出:

trick d
trick e
['trick d', 'trick e']
['trick d', 'trick e']

DogStr和DogList之间的区别在于,我将tricks视为前者的字符串,将后者视为列表

在处理DogStr时,tricks的行为就像一个实例变量。但是对于DogList,tricks的行为就像一个类变量

我希望在两个调用上看到相同的行为,即:如果输出的最后两行是相同的,那么前两行应该是相同的

所以我想知道。对此有何解释


Tags: 代码importselfadddefwithsysclass
1条回答
网友
1楼 · 发布于 2024-09-22 20:35:19

区别不在于对象的类型,而在于代码对它做了什么

这两者之间有很大的区别:

self.tricks = trick

以及:

self.tricks.append(trick)

第一个self.tricks = trickself的属性tricks赋值

第二个self.tricks.append(trick)检索self.tricks并对其调用一个方法(在这里修改其值)


在您的例子中,问题是没有在self实例上定义tricks,因此self.tricks.append获取类的tricks属性并对其进行修改,但是self.tricks = ...self上创建了一个新属性

其中一个是字符串,另一个是列表这一事实实际上并不相关。如果两者都是列表,那就一样了。 请注意,它们不能都是字符串,因为字符串是不可变的,因此没有append方法

如何修复

这是错误的:

def add_trick(self, trick):
    self.tricks = trick

如果tricks是类属性,add_trick应该是类方法:

@classmethod
def add_trick(cls, trick):
    cls.tricks = trick

如果有理由将add_trick作为实例方法,那么只需执行以下操作:

def add_trick(self, trick):
    DogStr.tricks = trick

相关问题 更多 >