实例和类变量

时间:2014-09-30 21:40:52

标签: python python-2.7

我需要帮助编写符合我认为应该做的代码。

以下是代码:

class Food:
    kind = 'fruit'
    def __init__(self, name):
        self.name = name

a = Food('tomato')
b = Food('cabbage')

print 'a ->', a.kind
print 'b ->', b.kind
print 'change a\'s kind'
a.kind = 'veg'
print 'a ->', a.kind
print 'b ->',b.kind
print 'change kind in the class'
Food.kind = 'meat'
print 'a ->', a.kind
print 'b ->', b.kind

我得到的输出是:

a -> fruit
b -> fruit
change a's kind
a -> veg
b -> fruit
change kind in the class
a -> veg
b -> meat

这是让我困惑的最后结果。如果我已经将'kind'正确地声明为类属性,那么当我在类中使用'Food.kind ='更改它时,它肯定会为两个实例更改它。实际上,当我通过其中一个实例给它新值时,我预计它会改变,但它只改变了一个。我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

属性查找从实例的字典开始,因此在课程中更改kind不会影响* a的{​​{1}}属性。但是仍然没有该属性的类的其他实例仍会在类字典中查找它,或者如果在kind中找不到,则在类树中进一步查找。

Food

由于此处没有基类,因此在>>> a.kind = 'veg' >>> a.__dict__ {'kind': 'veg', 'name': 'tomato'} >>> b.__dict__ {'name': 'cabbage'} 之后,对于不存在的属性,属性查找将立即停止,导致Food

AttributeError

请注意,新式类 special methods始终在类而非实例中查找。但是,由于您使用的是旧式类(在Python 3中删除),因此不会出现这种情况。但建议始终使用新式类(即继承自Python 2中的>>> a.foo Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> a.foo AttributeError: Food instance has no attribute 'foo' )。

您应该阅读:New-style and classic classes.


* 可变类属性(列表,字典等)在这里是一个例外,从实例或类对它们进行就地操作将反映在类和其他实例中的任何位置(除非实例使用相同名称定义新属性): / p>

object

答案 1 :(得分:0)

您可能知道在C ++ / Java中,通过实例引用静态成员是不受欢迎的。相反,我们鼓励您通过类引用在Java中引用静态成员,例如:

theThing.value = 1; // bad
Thing.value = 1; // good

在Python中,当读取实例上的字段时,Python将首先查看实例的字段。如果未找到实例字段,则将检查实例的类字段。

写入字段时,写入的字段始终被引用的对象 - 是实例或类。例如:

theThing.value = 1 # creates an instance field if one does not exist
Thing.value = 1 # creates a class field if one does not exist

因此,当读取kinda.kind的值时,将始终读取实例字段(除非删除该字段);并且b.kind将始终读取类字段(除非创建了实例字段)。