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

在python中继承,以便调用所有基函数

  •  1
  • Nikwin  · 技术社区  · 16 年前

    基本上,我要做的是:

    class B:
        def fn(self):
            print 'B'
    
    class A:
        def fn(self):
            print 'A'
    
    @extendInherit
    class C(A,B):
        pass
    
    c=C()
    c.fn()
    

    并让输出为

    A
    B
    

    我将如何实现扩展继承修饰符?

    3 回复  |  直到 16 年前
        1
  •  4
  •   Jochen Ritzel    16 年前

    这不是装饰工的工作。你想要完全改变一个类的正常行为,所以这实际上是一个元类的工作。

    import types
    
    class CallAll(type):
        """ MetaClass that adds methods to call all superclass implementations """
        def __new__(meta, clsname, bases, attrs):
            ## collect a list of functions defined on superclasses
            funcs = {}
            for base in bases:
                for name, val in vars(base).iteritems():
                    if type(val) is types.FunctionType:
                        if name in funcs:
                            funcs[name].append( val )
                        else:
                            funcs[name] = [val]
    
            ## now we have all methods, so decorate each of them
            for name in funcs:
                def caller(self, *args,**kwargs):
                    """ calls all baseclass implementations """
                    for func in funcs[name]:
                        func(self, *args,**kwargs)
                attrs[name] = caller
    
            return type.__new__(meta, clsname, bases, attrs)
    
    class B:
        def fn(self):
            print 'B'
    
    class A:
        def fn(self):
            print 'A'
    
    class C(A,B, object):
        __metaclass__=CallAll
    
    c=C()
    c.fn()
    
        2
  •  1
  •   Alex Martelli    16 年前

    元类是一个可能的解决方案,但有点复杂。 super 可以非常简单地完成(当然,对于新的样式类:没有理由在新代码中使用遗留类!):

    class B(object):
        def fn(self):
            print 'B'
            try: super(B, self).fn()
            except AttributeError: pass
    
    class A(object):
        def fn(self):
            print 'A'
            try: super(A, self).fn()
            except AttributeError: pass
    
    class C(A, B): pass
    
    c = C()
    c.fn()
    

    您需要try/except来支持单个或多个继承的任何顺序(因为在某些时候,沿着方法解析顺序mro,定义一个名为 fn ,您需要捕获并忽略结果 AttributeError )但正如你所看到的,不同于你对不同答案的评论,你似乎在想什么,你不一定需要重写。 FN 在leafmost类中,除非需要在此类重写中对该类执行特定的操作-- 超级的 在纯继承(非重写)方法上也可以正常工作!

        3
  •  1
  •   Neil Santos    16 年前

    我个人不会尝试用一个装饰器来做这个,因为我使用了新的样式类和 super() ,可以实现以下功能:

    >>> class A(object):
    ...     def __init__(self):
    ...         super(A, self).__init__()
    ...         print "A"
    ... 
    >>> class B(object):
    ...     def __init__(self):
    ...         super(B, self).__init__()
    ...         print "B"
    ... 
    >>> class C(A, B):
    ...     def __init__(self):
    ...         super(C, self).__init__()
    ... 
    >>> foo = C()
    B
    A
    

    我可以想象方法调用会以同样的方式工作。

    推荐文章