Python3继承中的类变量初始化

时间:2017-08-13 03:04:26

标签: python-3.x oop inheritance initialization

我有一个基类A,两个子类BC继承自AA中的一些变量可以共享A个对象,所以我选择使用类变量,这些类变量只应初始化一次,我可以在A中通过显式测试并设置A.some_var来执行此操作。

示例代码(使用显式类名):

from queue import Queue


class A:
    data_queue = None
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if A.data_queue is None:
            A.data_queue = Queue()


class B(A):
    pass


class C(A):
    pass


b = B()
c = C()

b.data_queue.put(5)
c.data_queue.get()  # Works fine

但是,我不认为这是一个好主意,因为在开发过程中可能会更改类名。

我也尝试了type,但这样变量在所有B个对象或C个对象之间共享,因为type(self)返回B或{{1 }}

C

那么,有没有更好的方法在没有显式类名的from queue import Queue class A: data_queue = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if type(self).data_queue is None: type(self).data_queue = Queue() class B(A): pass class C(A): pass b = B() c = C() b.data_queue.put(5) c.data_queue.get() # Block 中初始化类变量?

1 个答案:

答案 0 :(得分:0)

经过一番挣扎,我找到了一些解决方案,虽然它不太好,但它以某种方式实现了我的目标。

解决方案1:使用装饰器设置对类的引用

示例代码:

from queue import Queue


def cls_ref(cls):  # With this decorator, cls refs its self
    cls.cls = cls
    return cls


@cls_ref
class A:
    data_queue = None
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cls = self.cls
        if cls.data_queue is None:
            cls.data_queue = Queue()


class B(A):
    pass

class C(A):
    pass


b = B()
c = C()

b.data_queue.put(5)
c.data_queue.get()  # Works fine

解决方案2:使用限定名称的延迟评估

根据qualified name的定义:

  

虚线名称,显示从模块的全局范围到a的“路径”   在PEP中定义的该模块中定义的类,函数或方法   3155.对于顶级函数和类,限定名称与对象名称相同:

>>> class C:
...     class D:
...         def meth(self):
...             pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'

示例代码:

from queue import Queue


class LazyInit:
    def __init__(self, name):
        self.name = name
    def __get__(self, instance, owner):
        return globals()[self.name]


class A:
    cls = LazyInit(locals()['__qualname__'])
    data_queue = None
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cls = self.cls
        if cls.data_queue is None:
            cls.data_queue = Queue()


class B(A):
    pass

class C(A):
    pass


b = B()
c = C()

b.data_queue.put(5)
c.data_queue.get()  # Works fine

如果还有其他更好的解决方案,请解决我的问题。 :)