如何使用classmethod工厂函数实现继承

How to achieve inheritance using classmethod factory functions

如何在使用 classmethod approach for implementing factory functions 时 use/reuse 在 parent class 中实现?

在下面的例子中,class A 没问题,但 class B 坏了。

class A(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)
    @classmethod
    def from_jdata(cls, data):
        if '_id' in data:
            data['uuid'] = data['_id']
            del data['_id']
        return cls(**data)

class B(A):
    def __init__(self, **kwds):
        super(B, self).__init__(**kwds)
    @classmethod
    def from_jdata(cls, data):
        # goal: make an instance of B, 
        # using the logic that is implemented in A.from_jdata
        # But does some extra stuff, akin to:
        res = A.from_jdata(B, data)
        res.__dict__['extra']='set'
        return res

上下文是我正在尝试根据 JSON 配置数据实例化实例。继承层次比两个 class 更深,即有多个 children of class B。继承层次结构的根在工厂函数中做了一些有用的事情。 Children class应该 re-use 但要添加一些额外的操作。

使用super,当然:

class A(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)
    @classmethod
    def from_jdata(cls, data):
        if '_id' in data:
            data['uuid'] = data['_id']
            del data['_id']
        return cls(**data)

class B(A):
    def __init__(self, **kwds):
        super(B, self).__init__(**kwds)
    @classmethod
    def from_jdata(cls, data):
        # goal: make an instance of B,
        # using the logic that is implemented in A.from_jdata
        # But does some extra stuff, akin to:
        res = super().from_jdata(data)
        # res = super(B, cls).from_jdata(data) # in python 2
        res.__dict__['extra']='set'
        return res

在行动:

In [6]: b = B.from_jdata({'_id':42, 'foo':'bar'})

In [7]: vars(b)
Out[7]: {'foo': 'bar', 'uuid': 42, 'extra': 'set'}

请注意,您尝试执行的操作不会起作用,因为 @classmethod 创建了一个描述符,当从 class 或 class 调用时绑定 class实例。您必须使用类似以下内容的方法访问原始函数:

res = A.__dict__['from_jdata'].__func__(B, data)

要使其工作,但只需使用 super,这就是它的用途。