Python:类属性的继承(列表)

发布于 2024-08-25 14:17:29 字数 642 浏览 7 评论 0原文

从超类继承类属性,然后更改子类的值可以正常工作:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

导致输出:
10
10
10
5
这很好:弓箭手继承了单位的值,但是当我更改弓箭手的值时,单位的值保持不变。

现在,如果继承的值是一个列表,浅复制效果就会发生,超类的值也会受到影响:

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

输出:
10
10
5
5

从超类继承列表时是否有办法“深复制”列表?

非常感谢
佐野

inheriting a class attribute from a super class and later changing the value for the subclass works fine:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

leads to the output:
10
10
10
5
which is just fine: Archer inherits the value from Unit, but when I change Archer's value, Unit's value remains untouched.

Now, if the inherited value is a list, the shallow copy effect strikes and the value of the superclass is also affected:

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

Output:
10
10
5
5

Is there a way to "deep copy" a list when inheriting it from the super class?

Many thanks
Sano

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

格子衫的從容 2024-09-01 14:17:29

这不是浅拷贝或深拷贝的问题,而是引用和作业的问题。

第一种情况 Unit.valueArcher.value 是引用相同值的两个变量。当您执行 Archer.value = 5 时,您正在为 Acher.value 分配一个新引用。

要解决您的问题,您需要为 Archer.list 分配一个新的列表值。

如果这些值仅由类方法访问,那么最简单的解决方案是在类初始化时进行赋值。

It is not a matter of shallow or deep copies, it is a matter of references and assignments.

It the first case Unit.value and Archer.value are two variables which reference the same value. When you do Archer.value = 5, you are assigning a new reference to Acher.value.

To solve your problem you need to assign a new list value to the Archer.list.

If these values are only going to be accessed by class methods, then the simplest solution is to do the assignment when the class is initialized.

唯憾梦倾城 2024-09-01 14:17:29

迈克尔的答案很好而且简单,但是如果您希望避免必须将该行添加到每个 Unit 子类中 - 也许您有一堆类似的其他列表,元类是解决问题

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

输出的一种简单方法:

[10]
[10]
[10]
[5]

您也可以扩展这个相同的想法来自动查找和复制 Unit 中定义的列表(和字典)

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass

Michael's answer is nice and simple, but if you wish to avoid having to add that line to each Unit subclass - maybe you have a bunch of other lists like that one, a metaclass is an easy way to solve the problem

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

output:

[10]
[10]
[10]
[5]

You can also extend this same idea to automatically find and copy up lists (and dicts) defined in Unit

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass
逆光下的微笑 2024-09-01 14:17:29

您可以复制 Archer 定义中的列表:

class Archer(Unit):
    listvalue = Unit.listvalue[:]

You coud copy the list in the definition of Archer:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文