Python 如何自动向某些子类添加类变量
这将创建所有实例并将它们放入Python 如何自动向某些子类添加类变量,python,python-2.7,Python,Python 2.7,这将创建所有实例并将它们放入A.\u all。我想要的是将C的实例放在C.\u all(对于C也是如此) 我可以这样定义B和C: class A(object): _all = set() def __new__(cls): obj = super(A,cls).__new__(cls) cls._all.add(obj) return obj class B(A): pass class C(A): pass
A.\u all
。我想要的是将C
的实例放在C.\u all
(对于C也是如此)
我可以这样定义B
和C
:
class A(object):
_all = set()
def __new__(cls):
obj = super(A,cls).__new__(cls)
cls._all.add(obj)
return obj
class B(A):
pass
class C(A):
pass
b = B()
c = C()
那就行了。然而,这感觉像是重复代码,如果我在下一步子类A
时忘记添加\u all
,或者拼写错误\u all
,我很可能会很难调试错误
如何做好这一点?将
\u all
设置为None
,如果仍然None
,则在\u new\u
中创建您的集合,为每个类提供自己的副本:
class B(A):
_all = set()
class C(A):
_all = set()
这里有一个元类:
class A(object):
_all = None
def __new__(cls):
obj = super(A,cls).__new__(cls)
if cls._all is None:
cls._all = set()
cls._all.add(cls)
return obj
在Python 3中,A
的定义必须是:
class make_all_meta(type):
def __init__(cls, name, bases, dic):
type.__init__(cls, name, bases, dic)
cls._all = set()
class A(object):
__metaclass__ = make_all_meta
这正是我要建议的方法。你也可以用一个元类来做,虽然这稍微复杂一点。元类的方式感觉更“正确”,但我担心以后会更加复杂。此外,我不能做像
len(B._all)==0这样的事情,因为至少要实例化一个B
,B._allis None
我已经发布了一个带有元类的答案。没错,它确实简化了len()
问题。当然,您也可以首先将\u all
定义为空元组或其他内容,而不是None
。此解决方案假定在所有其他子类的第一个实例之前不会创建任何实例。我建议至少做断言cls不是\uuuuu new\uuuuu
中的一个。它不应该是cls.\u all.add(obj)
而不是cls.\u all.add(cls)
?
class A(metaclass=make_all_meta):
pass