Python 抽象方法上的装饰器

Python 抽象方法上的装饰器,python,decorator,abc,Python,Decorator,Abc,在python中,有没有一种方法可以使抽象方法上的装饰器贯彻到派生实现中 例如,在 import abc class Foo(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod @some_decorator def my_method(self, x): pass class SubFoo(Foo): def my_method(self, x): pri

在python中,有没有一种方法可以使抽象方法上的装饰器贯彻到派生实现中

例如,在

import abc

class Foo(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @some_decorator
    def my_method(self, x):
        pass

class SubFoo(Foo):
    def my_method(self, x):
        print x

据我所知,
subfo
我的\u方法
不会被
某个装饰者装饰。是否有某种方法可以实现这一点,而不必单独修饰
Foo
的每个派生类?

我的解决方案是扩展超类的方法而不重写它

import abc

class Foo(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @some_decorator
    def my_method(self, x):
        pass

class SubFoo(Foo):
    def my_method(self, x):
        super().my_method(x)  #delegating the call to the superclass
        print x

据我所知,这在Python中是不可能的,也不是一个好的策略。这里有更多的解释

根据报告:

当abstractmethod()与其他方法描述符结合应用时,它应该作为最内部的装饰器应用,如以下使用示例所示:

换句话说,我们可以这样编写您的类(Python 3风格):

那又怎么样?如果您从
AbstractClass
派生,并尝试重写
info
属性,而不指定
@property
装饰器,则会造成很大的混乱。请记住,为了简洁起见,属性(这只是一个示例)的类方法通常使用相同的名称:

class Concrete(AbstractMethod):

    @property
    def info(self):
        return

    @info.setter
    def info(self, new_info):
        new_info

在这种情况下,如果您没有重复
@属性
@info.setter
装饰器,就会造成混乱。用Python术语来说,这也行不通,属性放在类本身上,而不是实例上。换句话说,我想这是可以做到的,但在我看来,它最终会产生令人困惑的代码,这些代码不像重复几行装饰代码那么容易阅读。

这当然是可能的。在Python中几乎没有什么做不到的,哈哈!我会让你决定这是否是个好主意

class MyClass:
    def myfunc():
        raise NotImplemented()

    def __getattribute__(self, name):
        if name == "myfunc":
            func = getattr(type(self), "myfunc")
            return mydecorator(func)
        return object.__getattribute__(self, name)

(还没有测试语法,但应该给你一个想法)

我将把它编码为两种不同的方法,就像在标准方法工厂模式描述中一样


Jinksy的回答对我不起作用,但稍加修改就起了作用(我用了不同的名字,但想法应该很清楚):

def my_decorator(func):
def包裹(自身、x、y):
打印('开始')
结果=func(self,x,y)
打印('结束')
返回结果
退货包装
A类(ABC):
@抽象方法
def f(自身、x、y):
通过
@我的装饰师
def f_装饰(自、x、y):
返回self.f(x,y)
B(A)类:
def f(自身、x、y):
返回x+y
B().f_(1,3)
[输出:]
开始
结束
4.
请注意,这与Jinksy编写的内容之间的重要区别在于,抽象方法是f,当调用
B()时,调用的是继承的非抽象方法


据我所知,
f_decoration
可以正确定义,因为
abstractmethod
decorator没有干扰decorator
my_decorator

,我担心它只是具有广泛的魔力。调用抽象方法
\u my\u method
并使用非抽象、非重写的
my\u方法
是否是一种替代方法,它基本上可以
一些装饰程序(self.\u my\u method)(*args,**kwds)
?@delnan-Hmm,是的,我希望在广泛的元类魔法和你的好建议之间可能会有一个解决方案,那就是稍微干净一点。但是我想我会做我必须做的。你试过这个吗?这违背了抽象方法的目的。抽象方法的全部思想是它们必须被子类重写。因此,您不会对其调用
super()
。事实上,除了标记为抽象以确保未使用
super()
之外,我通常会让我的抽象方法引发一个
NotImplementedError
。使用抽象方法的默认实现没有什么错。
class MyClass:
    def myfunc():
        raise NotImplemented()

    def __getattribute__(self, name):
        if name == "myfunc":
            func = getattr(type(self), "myfunc")
            return mydecorator(func)
        return object.__getattribute__(self, name)
class Foo(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @some_decorator
    def my_method(self, x):
        self.child_method()

class SubFoo(Foo):
    def child_method(self, x):
        print x