0

我有一个基类,它有一个空白列表作为类属性。许多子类继承自这个基类。目的是将此列表类属性与类方法结合使用,以允许每个子类跟踪其自己的特定实例集。每个类都应该有一个单独的列表,其中只包含它自己的实例。

当我对这个继承方案进行简单的实现时,在调试期间我注意到实际上每个子类都与类属性共享完全相同的列表,并且我再次对 python 通过引用传递列表这一事实感到有趣。仔细观察,似乎父类的每个类属性、方法和值都只是通过引用传递给每个子类,并且除非在子类的定义中明确覆盖特定属性,否则这不会改变。

在创建子项时重新初始化子项的类变量的最佳方法是什么?理想情况下,我想要一种方法来确保每个孩子都以 cls.instances 属性开头,该属性是一个唯一的空白列表,其中任何孩子都没有额外的代码。否则,我首先要为继承而烦恼什么?(不要回答)

4

4 回答 4

3

没有不尊重@DanielRoseman 和他有见地的回答,但我想我会准确地写出你将如何使用元类来完成我理解你想要完成的事情:

mc.py:

class Meta(type):
    def __init__(cls, name, bases, attrs):
        cls.foo = []

class A:
    __metaclass__ = Meta

class B(A):
    pass

鉴于这种:

>>> import mc
>>> mc.A.foo
[]
>>> mc.A.foo.append(1)
>>> mc.A.foo
[1]
>>> mc.B.foo
[]
于 2012-05-18T20:45:14.380 回答
1

这就是你可能需要进入元类的地方。您的意思是,每次定义新的子类时,都需要一组新的变量。因此,元类是类类型的类:每次定义子类时,您都在实例化元类的新实例。每个元类实例都可以有自己的实例变量,这意味着每个子类都有自己的一组类变量。

在Marty Alchin 的博客上有一篇关于如何使用元类来做这类事情的精彩文章。

于 2012-05-18T20:34:25.980 回答
0

你的意思是这样的:

    >>> class Foo():
    ...   alist = []
    ...   def __init__(self):
    ...     pass
    >>> foo = Foo()
    >>> foo.alist
    []
    >>> Foo.alist
    []
    >>> Foo.alist.append(7)
    >>> Foo.alist
    [7]
    >>> foo.alist
    [7]
    >>> foo2 = Foo()
    >>> foo2.alist
    [7]
于 2012-05-18T20:32:23.727 回答
0

我认为您在这里遇到的问题是类实际上是对象,而类成员是类的type类型对象的成员,而不是其实例的成员。从这个角度来看,很容易看出为什么子类实际上没有父类级别成员的唯一实例。我过去用来解决此类问题的一种方法是使.instances父类中的类变量成为字典,然后在父类的__init__方法中,在存储在.instances字典中的键下的列表中对每个子类的实例进行编目是self类型。请记住,即使在父范围内,执行type()onself也会给您直接创建对象的类型,而不是本地范围的类型。

于 2012-05-18T20:35:27.420 回答