Seb*_*sen 3 python attributes object instance python-3.x
(特别是就它们在“正常使用”下的行为而言,在内部我认为它们很可能以不同的方式实现)
以这两个类为例:
class A:
d = 4
class A:
def __init__(self, d=4):
self.d = d
Run Code Online (Sandbox Code Playgroud)
无论您选择哪个版本,当您运行以下代码时,您都会得到相同的结果:
a2 = A()
a = A()
print(a.d) # 4
a.d = 2
print(a.d) # 2
print(a2.d) # 4
Run Code Online (Sandbox Code Playgroud)
读完后我想到了这个问题:
类变量和具有默认值的实例变量之间有什么区别吗?
嗯,显然是的:类属性(不是“变量”)属于类,实例属性属于实例。
在什么情况下我应该使用哪个版本?
当您希望属性由类的所有实例共享时,请使用类属性;当您希望属性特定于该具体实例时,请使用实例属性。在实践中,您很少需要类属性。
请注意,如果为类和实例定义相同的属性,则实例上的属性将隐藏类的属性。
注意:上面是一个非常非常粗略的简化,但否则我需要解释整个 Python 对象模型,这值得一本书
以这两个类为例(...)无论您选择什么版本,当您运行下面的代码时,您都会得到相同的结果
是的,这是该代码片段所期望的。
为了a:
在第一种情况下,当您第一次 print 时a.d,a没有实例属性d,因此您将获得类属性值。然后,您通过分配来创建实例属性a.d,从那时起它就隐藏了类属性。
在第二种情况下,a.d最初有它的默认值,然后你将它重新绑定到另一个值......非常普通的东西。
为了a2:
在第一种情况下,a2.a总是会4因为您没有使用实例属性来隐藏它,所以它从类中获取值。
在第二种情况下,它总是4因为您没有重新绑定实例属性,所以它仍然是默认值。
现在尝试使用列表作为属性进行相同的操作,并将其附加到列表而不是重新绑定它:
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)
Run Code Online (Sandbox Code Playgroud)
最后一点:您可能已经看到(或者有一天您可能会看到)使用类属性作为实例的默认值的代码 - 或者您可能会尝试自己这样做(因此提到实例属性的“默认”值) ) -,如第一个示例所示。这是不好的做法。它充其量是令人困惑的,如果属性是可变类型,则可能导致错误的行为。