python 类属性

23 投票
3 回答
23206 浏览
提问于 2025-04-15 23:15

我有一个关于Python中类属性的问题。

class base :
    def __init__ (self):
        pass
    derived_val = 1

t1 = base()
t2 = base()

t2.derived_val +=1
t2.__class__.derived_val +=2
print t2.derived_val             # its value is 2
print t2.__class__.derived_val   # its value is 3

结果是不同的。我还使用了id()函数来查看t2.derived_valt2.__class__.derived_val的内存地址,它们是不同的。我的问题是derived_val是类属性。为什么在上面的例子中它们会不同呢?是因为类的实例会在自己的地方复制一个derived_val,而不是直接使用类属性吗?

3 个回答

4

还有一种方法(可能更简洁)来展示这个:

class A():
   a1 = []
x = A()
y = A()
x.a1.append("test")
x.a1, y.a1
(['test'], ['test'])

class B():
   b1 = None
   def __init__(self):
      self.b1 = list()
r = B()
s = B()
r.b1.append("test")
r.b1, s.b1
(["test"], [])
4

你可以在 这里这里 查看相关内容。

__class__ 属性表示对象所属的类。所以在你的例子中,这种情况和静态变量有点像。t2.__class__.derived_val 指的是属于这个类的变量,而不是属于 t2 的变量。

47

在编程中,有两种属性:类属性和实例属性。

当你写

class base :
    derived_val = 1

你是在定义一个类属性。这个derived_val就成了base.__dict__里的一个键。

t2=base()
print(base.__dict__)
# {'derived_val': 1, '__module__': '__main__', '__doc__': None}
print(t2.__dict__)
# {}

当你写t2.derived_val时,Python会先在t2.__dict__里找这个'derived_val'。如果找不到,它会去t2的父类里查找是否有这个'derived_val'的键。

print(t2.derived_val)
print(t2.__dict__)
# 1
# {}

但是,当你给t2.derived_val赋值时,你实际上是在给t2添加一个实例属性。这时,derived_val这个键就被添加到了t2.__dict__里。

t2.derived_val = t2.derived_val+1
print(t2.derived_val)
print(t2.__dict__)
# 2
# {'derived_val': 2}

需要注意的是,这时有两个derived_val属性,但只有实例属性是很容易访问的。类属性只能通过base.derived_val或者直接访问类字典base.__dict__来获取。

撰写回答