Python 类方法和函数的装饰器

Python 类方法和函数的装饰器,python,decorator,Python,Decorator,我有一个装饰师 def deco(func): def inner(params): #< DO STUFF WITH func > return inner 我希望能够在属于GenericClass子类的类上修饰“method”方法,例如检查输入/输出或处理异常(方法“method”将被重写) 我想做的是 class ChildClass(GenericClass): @deco def method(self,params):

我有一个装饰师

def deco(func):
    def inner(params):
        #< DO STUFF WITH func >
    return inner
我希望能够在属于GenericClass子类的类上修饰“method”方法,例如检查输入/输出或处理异常(方法“method”将被重写)

我想做的是

class ChildClass(GenericClass):
    @deco
    def method(self,params):
        #< NEW METHOD >
class子类(GenericClass):
@德科
def方法(自身、参数):
#<新方法>

我不是一个专业的python开发人员,这个级别的所有文档都非常混乱(例如元类、装饰器中的微妙之处、
\uuu调用\uuu
方法等等),我没有找到解决方案。您基本上是在问如何编写一个可以应用于函数和方法的装饰器。有可能:

def deco(func):
    def inner(*args):
        print('DECORATED: args={}'.format(args))
        func(*args)
    return inner

class Class:
    @deco
    def method(self, param): print('PARAM is {}'.format(param))

@deco
def func(a, b, c): print('{} {} {}'.format(a, b, c))

Class().method('X')

func(1, 2, 3)
输出:

DECORATED: args=(<__main__.Class instance at 0x7f740c6297a0>, 'X')
PARAM is X
DECORATED: args=(1, 2, 3)
1 2 3
装饰:args=(,'X') 参数是X 装饰:args=(1,2,3) 1 2 3 p.S.


一年后,我在这里发现了一个有用的帖子(8年前被问到):。如果您关心修饰函数的实际参数,那么这里描述的方法将非常有用。

我找到了它。诀窍在于模块级函数(我想闭包除外,您可能无论如何都不想修饰闭包)有一个简单的名称,而方法的限定名称中至少有两个部分。 忘记inspect.ismethod吧——由于某种原因,它在这种情况下不起作用,尽管它应该是一个明显的选择,可能是一个bug

def can(*fargs):
    def wrapper(func):
        if len(func.__qualname__.split('.')) > 1:
            def calling(self, *args, **kwargs):
                self, thing = args[0], args[1]
                do_stuff(thing)
                func(*args, **kwargs)
        else:
            def calling(*args, **kwargs):
                thing = args[0]
                do_stuff(thing)
                func(*args, **kwargs)
        return calling
    return wrapper

class C:
    @can(2, 3)
    def test(self, x):
        print(7, ismethod(self.test), x)

@can()
def test(x):
    print(8, ismethod(test), x)

c = C()
c.test(12)

test(8)

不确定这里的问题是什么,如果你的decorator是一个普通函数,那么你不应该对它进行任何修饰。当我使用decorator时,它也会将“self”作为内部函数的参数。我想让我的装饰器具有足够的通用性,以便能够在未嵌入类的函数中使用它。我猜您在
deco
中不使用
params
,否则,您必须使用
args[index]
访问它们,其中索引可以移动,即函数的第一个实际参数的索引为0,方法的索引为1。为了简单起见,你可以使用负指数,但前提是参数的数量是恒定的,这只是一个荣耀的问题。。。有没有一种方法可以在父类级别包含decorator操作?i、 e.在父级编写检查代码,即使在子级调用该方法,也会激活该检查。我不确定我是否正确理解您的意思。您的意思是您想修饰基方法,以便子类中的重写方法也被修饰?不,不可能。来自Python的禅宗:
显式优于隐式。
。您必须显式地修饰每个方法/函数
def can(*fargs):
    def wrapper(func):
        if len(func.__qualname__.split('.')) > 1:
            def calling(self, *args, **kwargs):
                self, thing = args[0], args[1]
                do_stuff(thing)
                func(*args, **kwargs)
        else:
            def calling(*args, **kwargs):
                thing = args[0]
                do_stuff(thing)
                func(*args, **kwargs)
        return calling
    return wrapper

class C:
    @can(2, 3)
    def test(self, x):
        print(7, ismethod(self.test), x)

@can()
def test(x):
    print(8, ismethod(test), x)

c = C()
c.test(12)

test(8)