我有一个基类A
,两个子类B
和C
继承自A
,A
中的一些变量可以共享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
中初始化类变量?
答案 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
如果还有其他更好的解决方案,请解决我的问题。 :)