为什么 Python 范围对于列表变量和字符串变量的行为似乎不同?
Why the Python scope seems to behave differently for list variable and string variable?
假设我有以下 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 技巧的行为就像一个 class 变量。
我期望在两个调用中看到相同的行为,即:如果输出的最后两行相同,那么前两行也应该相同。
所以我想知道。对此有何解释?
区别不在于对象的类型,而在于您的代码对其做了什么。
这两者有很大区别:
self.tricks = trick
和:
self.tricks.append(trick)
第一个 self.tricks = trick
为 self
的属性 tricks
赋值。
第二个 self.tricks.append(trick)
检索 self.tricks
并对其调用方法(此处修改其值)。
在您的情况下,问题是 self
实例上没有定义 tricks
,因此 self.tricks.append
获取 [=54] 的 tricks
属性=] 并对其进行修改,但 self.tricks = ...
在 self
上创建了一个新属性。
其中一个是字符串而另一个是列表这一事实并不真正相关。如果两者都是列表,那将是相同的。
请注意,它们不能都是字符串,因为字符串是不可变的,因此没有追加方法
如何解决?
这是错误的:
def add_trick(self, trick):
self.tricks = trick
如果tricks
是一个class属性,add_trick
应该是一个class方法:
@classmethod
def add_trick(cls, trick):
cls.tricks = trick
如果有理由让add_trick
成为实例方法,那么只需这样做:
def add_trick(self, trick):
DogStr.tricks = trick
假设我有以下 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 技巧的行为就像一个 class 变量。
我期望在两个调用中看到相同的行为,即:如果输出的最后两行相同,那么前两行也应该相同。
所以我想知道。对此有何解释?
区别不在于对象的类型,而在于您的代码对其做了什么。
这两者有很大区别:
self.tricks = trick
和:
self.tricks.append(trick)
第一个 self.tricks = trick
为 self
的属性 tricks
赋值。
第二个 self.tricks.append(trick)
检索 self.tricks
并对其调用方法(此处修改其值)。
在您的情况下,问题是 self
实例上没有定义 tricks
,因此 self.tricks.append
获取 [=54] 的 tricks
属性=] 并对其进行修改,但 self.tricks = ...
在 self
上创建了一个新属性。
其中一个是字符串而另一个是列表这一事实并不真正相关。如果两者都是列表,那将是相同的。 请注意,它们不能都是字符串,因为字符串是不可变的,因此没有追加方法
如何解决?
这是错误的:
def add_trick(self, trick):
self.tricks = trick
如果tricks
是一个class属性,add_trick
应该是一个class方法:
@classmethod
def add_trick(cls, trick):
cls.tricks = trick
如果有理由让add_trick
成为实例方法,那么只需这样做:
def add_trick(self, trick):
DogStr.tricks = trick