2017-05-27 61 views
0

我有一个名为A类:A是否有可能与父类的实例共享在子类insatnces中定义的方法引用?

>>> class A: 
    def __init__(self): 
     self.register = {} 


>>> 

类将是子类的B类。然而,类B包含的方法需要在类A的字典实例中注册为name: function对。这是类A可以使用该方法做的工作。

这里是我的意思的例子:

>>> class B(A): 
    def foo(self): 
     pass 
    def bar(self): 
     pass 


>>> b = B() 
>>> b.register # foo and bar were registered 
{'key': <foo function>, 'key2': <bar function>} 
>>> 

是否有解决这一惯用的方式?或者像这样的事情是不可能的,并且最好改变我的代码结构。


注意,因为我的寄存器是不是全球性的,这是不是Auto-register class methods using decorator副本,它是一个类的实例变量。这意味着使用所选答案中显示的元类是行不通的。

+0

您可以在底部添加TL,DR吗? –

+0

这是干什么用的;你想用它来实现什么样的行为?您不能在类定义时访问实例属性; *有*没有实例。 – jonrsharpe

+0

@jonrsharpe我想你的权利。我试图实现一个基于正则表达式的词法分析器。我试图让用户使用装饰器将某个正则表达式映射到函数。这样,只要特定的正则表达式匹配,函数就会被调用。我认为使用装饰器将是一个简洁的方法来做到这一点。 –

回答

1

如果将宣布你需要的所有类,之后担心例如寄存器必须在所有子类的所有声明的方法引用,你只需要在声明自己的子类时,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 
     ... 
2

我认为你在帖子中提到的链接this question确实可以用来解决你的问题,如果我理解正确的话。

您试图注册的信息全球信息。虽然您希望每个实例都有一个包含此全局信息的寄存器,但您真正需要做的是将全局寄存器复制到实例寄存器中。

相关问题