[英]How to use a decorator to modify mutable class variables?
我有以下代码:
class X(object):
items = []
class Y(X):
pass
class Z(X):
pass
我正在尝试创建一个装饰器,该装饰器仅将一个对象添加到Y的“项目”列表中。 所以下面的代码,
@addItems
class Y(X):
pass
应该在Y.items后面附加一些内容(例如,整数1),但不要修改X.items,Z.items或X的任何其他子类。基本上,Y.items应该具有items = [1]
但X.items和Z.items都应具有items = []
。 这是我创建的装饰器函数定义,旨在实现该目标:
def addItems(cls):
cls.items.append(1)
return cls
但是,这不起作用-当我使用装饰器时,它最终会修改X和X的所有其他子类的“项目”列表。这有什么用? 我知道Python的类属性在X的所有实例之间共享,但是,我不知道子类会受到影响。 也许这种行为只发生在可变属性上?
实现目标的正确方法是什么?
问题不在于装饰器。 您对items
属性的存储位置/方式存在误解。 Y
和Z
没有自己的items
属性。 而是只有一个items
属性。 您在X
上定义了它,如果执行Y.items
(或Z.items
),则由于在子类上找不到该属性,因此会在超类上动态查找它。 如果你X.items is Y.items
你会看到它演算值为真---只有一个items
清单。 这意味着,当您对其进行修改时,所有类都会看到该修改。
如果要为每个班级提供自己的items
列表,则必须为每个班级提供自己的items
列表:
class X(object):
items = []
class Y(object):
items = []
class Z(object):
items = []
除非您告知,否则Python绝不会复制任何内容。 仅仅因为您定义了一个继承自具有属性的类的子类,但这并不意味着Python会为该子类创建该属性的新副本。 它只是重复使用超类中的同一对象。
如果您想“神奇地”为每个类赋予自己的项目属性,则可以在装饰器中进行操作:
def addItems(cls):
cls.items = []
cls.items.append(1)
return cls
这首先将类的items
设置为空列表。 这实际上将属性设置在它所操作的特定类上,而不是在任何子类或超类上。 现在,当您访问它时,它将按预期工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.