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

2024-06-25 23:31:18 发布

您现在位置:Python中文网/ 问答频道 /正文

基本上,我想做的是:

class B:
    def fn(self):
        print 'B'

class A:
    def fn(self):
        print 'A'

@extendInherit
class C(A,B):
    pass

c=C()
c.fn()

然后让输出

^{2}$

我如何实现extendenherit装饰器?在


Tags: selfdef装饰passclassfnprintextendinherit
3条回答

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

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()

元类是一个可能的解决方案,但有点复杂。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,除非您需要在这样的重写中对该类做特定的操作super也可以在纯继承(而不是重写)方法上正常工作!在

我个人不会尝试使用decorator来实现这一点,因为使用新样式的类和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

我想方法调用也会以同样的方式工作。在

相关问题 更多 >