繁体   English   中英

如何使用装饰器修改可变的类变量?

[英]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属性的存储位置/方式存在误解。 YZ没有自己的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM