类方法的python装饰器

Posted

技术标签:

【中文标题】类方法的python装饰器【英文标题】:python decorator for class methods 【发布时间】:2018-07-14 23:22:17 【问题描述】:

我有一个装饰器来注册一些类方法。如何正确获取selfrun 参数?

类任务(对象): _tasks = [] @静态方法 定义寄存器(名称): def 装饰器(fn): @wraps(fn) def wrapper(self=None, run=True, *args, **kwargs): 如果不运行: 任务 = 默认字典() 任务['名称'] = 名称 任务['fn'] = getattr(self, fn.__name__, None) 任务['obj'] = 自我 任务['args'] = deepcopy(args) 任务['kwargs'] = deepcopy(kwargs) Task._tasks.append(任务) 别的: 返回 fn(self, *args, **kwargs) 返回包装 返回装饰器 类测试(对象): def __init__(self, name): self.name = 名称 @Task.register('foo') def foo(自我,v1,v2): print '在对象 中使用参数运行 foo '.format(self.name, v1, v2) @Task.register('你好') 定义你好(自我): print '在对象 中运行 hello '.format(self.name) 默认负载(自我): self.foo('1', '2', run=False) 自我.你好(运行=假) t1=测试('t1') t1.load()

Traceback(最近一次调用最后一次):

TypeError: wrapper() got multiple values for keyword argument 'run'

【问题讨论】:

您的代码没有您描述的错误。 (假设from functools import * 【参考方案1】:

您的问题与装饰器无关。以更简单的形式:您正在做的是:

def foo(run=False, *args, **kwargs):
    print(run, args, kwargs)

foo(1, 2, run=True)  # TypeError: foo() got multiple values for argument 'run'

根据您的函数签名,python 将尝试设置run=1args = (2,),然后运行到TypeError

一个修复 - 虽然不是一个很好的 - 可能是:

def foo(*args, **kwargs):
    run = kwargs.pop('run', False)  # run defaults to False; remove from kwargs
    print(run, args, kwargs)

【讨论】:

我正在做的是我想将一个“运行”参数传递给装饰器,这将告诉装饰器注册任务或执行它。但我不想在我的类方法中添加这个“运行”参数,因为它在方法中什么都不做。在这种情况下,我应该如何传递/处理“运行”参数? 你可以使用我所说的foo 作为你的wrapper 函数。更改其签名并从kwargs 获取run。这实际上是the other answer 已经详细建议的内容...... 是的,这可能是一个解决方案。谢谢!【参考方案2】:

run参数来自fun,所以尝试从函数的参数中获取:

from collections import defaultdict
from copy import deepcopy
from functools import wraps

class Task(object):
    _tasks = []

    @staticmethod
    def register(name):
        def decorator(fn):
            @wraps(fn)
            def wrapper(self=None, *args, **kwargs):
                run = kwargs.pop('run', True)
                if not run:
                    task = defaultdict()
                    task['name'] = name
                    task['fn'] = getattr(self, fn.__name__, None)
                    task['obj'] = self
                    task['args'] = deepcopy(args)
                    task['kwargs'] = deepcopy(kwargs)
                    Task._tasks.append(task)
                else:
                    return fn(self, *args, **kwargs)

            return wrapper

        return decorator

【讨论】:

【参考方案3】:

Python3 似乎有更好的参数处理程序,但不知道如何在 python2 中执行此操作:

从 functools 导入包装 def optional_debug(func): @wraps(函数) def 包装器(*args,debug=False,**kwargs): 如果调试: print('调用', func.__name__) 返回函数(*args,**kwargs) 返回包装 @optional_debug 定义垃圾邮件(a,b,c): 打印(a,b,c) 垃圾邮件(1,2,3)#1,2,3 spam(1,2,3, debug=True) # 调用垃圾邮件 # 1 2 3

【讨论】:

以上是关于类方法的python装饰器的主要内容,如果未能解决你的问题,请参考以下文章

32.Python面向对象描述符运算符底层装饰器:闭包-闭包参数-内置装饰器-类装饰器

32.Python面向对象描述符运算符底层装饰器:闭包-闭包参数-内置装饰器-类装饰器

类方法的python装饰器

Python 装饰器装饰类中的方法(转)

基于 Python 类的装饰器,带有可以装饰方法或函数的参数

python装饰器模块