我试图理解类属性在Python中是如何工作的。根据下面的例子,我感到困惑。你知道吗
#!/usr/bin/python3
class Bag:
val = 100
items = []
def add(self, x):
self.items.append(x)
print(self.items)
b1 = Bag()
b1.add('book')
b1.val += 1
print(b1.val)
b1.add('pen')
b1.val += 1
print(b1.val)
b2 = Bag()
b2.add('sketches')
b2.val += 1
print(b2.val)
b2.add('text')
b2.val += 1
print(b2.val)
b2.add('canvas')
b2.val += 1
print(b2.val)
预期输出:
['book']
101
['book', 'pen']
102
['book', 'pen', 'sketches']
103
['book', 'pen', 'sketches', 'text']
104
['book', 'pen', 'sketches', 'text', 'canvas']
105
看到的输出:
['book']
101
['book', 'pen']
102
['book', 'pen', 'sketches']
101
['book', 'pen', 'sketches', 'text']
102
['book', 'pen', 'sketches', 'text', 'canvas']
103
为什么共享列表和整数的不同副本之间不一致?你知道吗
下面是另一个示例,它显示了int
的不同行为。你知道吗
#!/usr/bin/python3
class Person:
cl_roll = 0
def __init__(self, name):
self.name = name
self.roll = self.next_roll()
print(self.roll, self.name)
@classmethod
def next_roll(cls):
cls.cl_roll += 1
return cls.cl_roll
p1 = Person('Eve')
p2 = Person('Abel')
p3 = Person('Eva')
基于先前输出的预期输出:
1 Eve
1 Abel
1 Eva
实际输出:
1 Eve
2 Abel
3 Eva
list
items
是类的所有实例中的一个共享对象。你用self.items.append(x)
修改它,但你永远不会创建另一个列表。所以每个对.items
的引用都在共享对象Bag.items
上工作但是,当你这么做的时候
这就像写作
因为
b1
还没有val
的单独值,所以得到的效果是:您正在为
b1.val
分配一个不同于Bag.val
的新值。你知道吗所以你的实例有一个共享的
items
,但是有单独的val
,因为你实际上把分配给了b1.val
等等我将把你的例子扩展一下
循序渐进:
self.items.append(x)
:首先,python尝试查找在
object (self.__dict__)
中是否有items
,如果没有,则尝试从类作用域中查找items
,并附加它。此表达式不返回任何内容。self.__dict__
在这个表达式之后是不变的。self.val += 1
这是int的扩充赋值。因此
__iadd__
将被调用,如果没有实现,则__add__
将被调用,它将始终返回一个新的int。旧的int不会更改,因为它是不可变的。详细说明你知道吗自我价值= 自我价值+1个
rhs
上的self.val
第一次引用class属性(因为b1.dict没有这个属性),它创建了一个新的int,这个int现在存储在对象的__dict__
(因为lhs)。。在rhs
中的第二次self.val
引用了self.__dict__
中的val,如果您本想做Bag.val += 1
,那么它将始终操作类变量(就像您的第二个示例)self.items1 += [x]
所以这也是
list.__iadd__
的增加。self.items1
对可变序列进行适当更改,对同一列表的引用也作为此表达式的一部分返回。因此,在这个语句之后,您应该看到self.__dict__
将包含items1
,但内容与Bag.__dict__['items1']
相同。你知道吗你的第二个例子完全不同:
此语句始终操作类变量。你知道吗
相关问题 更多 >
编程相关推荐