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

时间:2018-11-15 22:49:21

标签: python inheritance factory-pattern

使用classmethod approach for implementing factory functions时如何在父类中使用/重用实现?

在下面的示例中,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 B的子级。继承层次结构的根在工厂功能中起到了一些有用的作用。子类应该重新使用它,但要增加一些其他操作。

1 个答案:

答案 0 :(得分:1)

当然使用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创建了一个描述符,该描述符在从类或实例调用时绑定了该类。您将必须使用以下方式访问原始函数:

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

要使其正常工作,而只需使用super,这就是它的作用。