Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的继承,以便调用所有基函数_Python_Inheritance_Decorator_Multiple Inheritance - Fatal编程技术网

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

Python中的继承,以便调用所有基函数,python,inheritance,decorator,multiple-inheritance,Python,Inheritance,Decorator,Multiple Inheritance,基本上,我想做的是: 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 如何实现extendInherit装饰器?我个人不会尝试使用装饰器来实现这一点,因为使用新样式的类和super可以实现以下功能: >>> class

基本上,我想做的是:

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

如何实现extendInherit装饰器?

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

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

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

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

这不是装饰者的工作。您希望完全改变类的正常行为,因此这实际上是元类的工作

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

这不是装修工的工作。您希望完全改变类的正常行为,因此这实际上是元类的工作

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来支持单继承或多继承的任何顺序,因为在某个点上,在定义名为fn的方法的方法解析顺序MRO上将没有进一步的基础,您需要捕获并忽略结果AttributeError。但正如您所看到的,与您根据对不同答案的评论所想的不同,您不一定需要在最叶类中重写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来支持单继承或多继承的任何顺序,因为在某个点上,在定义名为fn的方法的方法解析顺序MRO上将没有进一步的基础,您需要捕获并忽略结果AttributeError。但正如您所看到的,与您根据对不同答案的评论所想的不同,您不一定需要在最叶类中重写fn,除非您需要在这种重写中执行特定于该类的操作-超级在纯继承而非重写的方法上也可以很好地工作

然而,在这里我仍然必须定义派生类中的每个函数。它们是单行函数,比如def fnself:super、self.fn,但我仍然需要为每个函数编写它。我正在寻找的是一种避免这种情况的方法。此外,为此,我必须使每个类都成为一个新样式的类。无论如何,您都应该使用新样式的类。Super是一个不错的选择。@Nikwin构造函数继承是python设计中没有的,因此如果您想在派生类中使用构造函数逻辑,是的,您必须显式调用构造函数。Explicit是python游戏的名称,我不能说我发现了一件坏事:@extraneon:我不担心构造函数,我想要的是派生类的函数调用所有同名的基类函数。但是,在这里我仍然必须定义派生类中的每个函数。它们是单行函数,比如def fnself:super、self.fn,但我仍然需要为每个函数编写它。我正在寻找的是一种避免这种情况的方法。此外,为此,我必须使每个类都成为一个新样式的类。无论如何,您都应该使用新样式的类。Super是一个不错的选择。@Nikwin构造函数继承是python设计中没有的,因此如果您想在派生类中使用构造函数逻辑,是的,您必须显式调用构造函数。Explicit是python游戏的名称,我不能说我发现了一件坏事:@extraneon:我不担心构造函数,我想要的是派生类的函数调用所有同名的基类函数。实际上,我更喜欢THC4k的解决方案随着OP的资格,他宁愿避免超级,这似乎更适合。然而,顺便说一句,元类只适用于新样式的类+尽管如此,对于nikow和extraneon来说,我还是更喜欢THC4k的解决方案随着OP的资格,他宁愿避免超级,这似乎更适合。然而,顺便说一句,元类只适用于新样式的类+然而,尼科和埃特莱昂的情绪都是如此。