是否可以与父 class 实例共享子 class 实例中定义的方法引用?

Is it possible to share a method reference defined in subclass insatnces with instances of the parent class?

我有一个 class 叫 A:

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


>>> 

class A 将被 class B 子class编辑。然而,class B 包含需要在 class A 字典的实例中注册为 name: function 对的方法。这样 class 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>}
>>> 

有没有惯用的方法来解决这个问题?或者这样的事情是不可能的,最好改变我的代码结构。


注意这不是 的副本,因为我的寄存器不是全局的,它是 class 的一个实例变量。这意味着使用所选答案中所示的 meta-class 将不起作用。

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

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

如果你将声明所有你需要的 classes,然后担心 instance 寄存器引用所有子 class 中声明的所有方法es,你只需要在声明子classes时执行一个"register"信息。这在 Python 3.6(但不是 3.5)和新的 __init_subclass__ mechanism 中很容易做到。在 Python 3.5 和之前的版本中,使用 metaclass 更容易执行。

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

这里的代码很简单 - 自定义字典 ​​class 会将 A.regiser 字典的 "copy on read" 值放入实例字典中。如果您需要一个包含此行为的更一致的字典(例如,一个将正确迭代其自身和后备字典的键、值和项目的字典),您最好实现 "FallbackDict" class作为 collections.abc.MutableMapping 的一个实例(并且只使用一个聚合字典来实际保存数据)

如果您计划在创建 "A" 的任何实例之前创建所有注册新方法的 classes - 或者如果新创建 classes 不必更新现有实例 - 但在这种情况下,您应该将 A.register 复制到 __init__.

中实例的 "self.register"

如果您不能更改为 Python 3.6,您还需要一个自定义元 class 来触发上面的 __init_subclass__ 方法。保持原样,这样您的代码就可以迁移到 Python 3.6 并删除元 class,并添加一个元 class,例如:

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
        ...