如果将宣布你需要的所有类,之后担心例如寄存器必须在所有子类的所有声明的方法引用,你只需要在声明自己的子类时,Performa的一个“注册”的信息。在Python 3.6(但不是3.5)中使用新的__init_subclass__
mechanism很容易。在Python 3.5和之前,使用元类更容易执行。
class FallbackDict(dict):
def __init__(self, fallback):
self.fallback = fallback
def __missing__(self, key):
value = self.fallback[key]
self[key] = value
return value
class A:
register = {}
def __init__(self):
# instance register shadows global register
# for access via "self."
self.register = FallbackDict(__class__.register)
def __init_subclass__(cls):
for attrname, value in cls.__dict__.items():
if callable(value):
__class__.register[attrname] = value
的代码在这里,就是要简单 - 自定义字典类将在A.regiser字典到实例字典的价值观“上读出的复制”。如果您需要包含此行为的更一致的字典(例如,将正确迭代本身和后备字典的键,值和项目的字典),最好将“FallbackDict”类实现为集合实例。 abc.MutableMapping(而只是使用汇总字典实际保留数据)
如果您计划在创建任何“A”实例之前创建所有注册新方法的类,则根本不需要定制字典“ - 或者新创建的类不必更新现有实例 - 但在这种情况下,您应该将A.register复制到__init__
中的实例”self.register“中。
如果您不能更改为Python 3.6,您还需要一个自定义元类来触发上面的__init_subclass__
方法。只要保持原样,以便您的代码已准备好移至Python 3.6并消除元类,并添加一个元类,如下所示:
class MetaA(type):
def __init__(cls, name, bases, namespace):
super().__init__(name, bases, namespace)
cls.__init_subclass__()
class A:
...
@clasmethod
def __init_subclass__(cls):
# as above
...
您可以在底部添加TL,DR吗? –
这是干什么用的;你想用它来实现什么样的行为?您不能在类定义时访问实例属性; *有*没有实例。 – jonrsharpe
@jonrsharpe我想你的权利。我试图实现一个基于正则表达式的词法分析器。我试图让用户使用装饰器将某个正则表达式映射到函数。这样,只要特定的正则表达式匹配,函数就会被调用。我认为使用装饰器将是一个简洁的方法来做到这一点。 –