- 类变量和具有默认值的实例变量之间有什么区别吗?
(特别是在“正常使用”下的行为方面,在内部我认为它们很可能以不同方式实现)
- 我应该在什么情况下使用哪个版本?
以这两个类为例:
class A:
d = 4
class A:
def __init__(self, d=4):
self.d = d
无论你选择什么版本,当你运行下面的代码时,你都会得到相同的结果:
a2 = A()
a = A()
print(a.d) # 4
a.d = 2
print(a.d) # 2
print(a2.d) # 4
看完之后我想到了这个问题:
最佳答案
Are there any differences between a class variable and an instance variable with a default value?
嗯,显然是的:类属性(不是“变量”)属于类,实例属性属于实例。
In what context should I use which version?
当您希望属性由类的所有实例共享时使用类属性,当您希望属性特定于该实例时使用实例属性。实际上,您很少需要类属性。
请注意,如果您为类和实例定义了相同的属性,则实例上的属性将覆盖类的属性。
nb:以上是非常非常粗略的简化,否则我需要解释整个 Python 对象模型,这值得写一整本书
Take these two classes as an example (...) no matter what version you choose, when you run the code below, you'll get the same result
是的,对于这个代码片段来说这是意料之中的。
对于a
:
在第一种情况下,当你第一次打印 a.d
时,a
没有实例属性 d
所以你得到类属性值。然后通过分配给它来创建实例属性 a.d
,然后它会隐藏类属性。
在第二种情况下,a.d
最初有它的默认值,然后你将它重新绑定(bind)到另一个值......很普通的东西。
对于a2
:
在第一种情况下,a2.a
将始终是 4
,因为您没有使用实例属性隐藏它,所以它从类中获取值。
在第二种情况下,它将始终是 4
,因为您没有重新绑定(bind)实例属性,所以它仍然是默认值。
现在用列表作为属性尝试同样的事情,并附加到列表而不是重新绑定(bind)它:
class A:
d = []
class B:
def __init__(self):
self.d = []
def test(cls):
print("test {}".format(cls.__name__))
a = cls()
print(a.d)
a.d.append(2)
print(a.d)
a2 = cls()
print(a2.d)
if __name__ == "__main__":
test(A)
test(B)
最后一点:您可能已经看到(或者有一天您可能会看到)代码使用类属性作为实例的默认值——或者您可能想自己这样做(因此提到了“默认”值实例属性)-,就像你的第一个例子一样。 这是不好的做法。它充其量是令人困惑的,如果属性是可变类型,则可能导致错误行为。
关于python - 具有默认值的类属性和实例变量之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59881485/