代码之家  ›  专栏  ›  技术社区  ›  Dave

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

  •  0
  • Dave  · 技术社区  · 6 年前

    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配置数据实例化实例。继承层次结构不仅仅是两个类,也就是说,有许多类的子类 . 继承层次结构的根在工厂函数中做了一些有用的事情。子类应该重用它,但要添加一些额外的操作。

    1 回复  |  直到 6 年前
        1
  •  1
  •   juanpa.arrivillaga    6 年前

    使用 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)