我已经看到许多Python装饰器的示例,它们是:

  • 函数样式修饰符(包装函数)
  • 类样式装饰器(实现__init____get____call__)
  • 不接受参数的
  • 装饰器
    带有参数
  • 装饰器
    “方法友好”的
  • 装饰器(即可以装饰类中的方法)
  • “功能友好”的
  • 装饰器(可以装饰普通功能
  • 可以装饰方法和函数的
  • 装饰器

    但是我从未见过一个可以完成上述所有操作的示例,并且在从各种答案到特定问题(例如this onethis onethis one (which has one of the best answers I've ever seen on SO))的综合答案,如何组合以上所有内容方面遇到困难。

    我想要的是一个基于类的装饰器,它可以装饰的方法或函数,以及,它需要至少一个附加参数。即,以便以下工作:
    class MyDecorator(object):
        def __init__(self, fn, argument):
            self.fn = fn
            self.arg = argument
    
        def __get__(self, ....):
            # voodoo magic for handling distinction between method and function here
    
        def __call__(self, *args, *kwargs):
            print "In my decorator before call, with arg %s" % self.arg
            self.fn(*args, **kwargs)
            print "In my decorator after call, with arg %s" % self.arg
    
    
    class Foo(object):
        @MyDecorator("foo baby!")
        def bar(self):
            print "in bar!"
    
    
    @MyDecorator("some other func!")
    def some_other_function():
        print "in some other function!"
    
    some_other_function()
    Foo().bar()
    

    我希望看到:
    In my decorator before call, with arg some other func!
    in some other function!
    In my decorator after call, with arg some other func!
    In my decorator before call, with arg foo baby!
    in bar!
    In my decorator after call, with arg foo baby!
    

    编辑:如果有关系,我正在使用Python 2.7。

    最佳答案

    您不需要弄乱描述符。在__call__()方法内创建包装函数并返回它就足够了。根据上下文,标准Python函数始终可以充当方法或函数:

    class MyDecorator(object):
        def __init__(self, argument):
            self.arg = argument
    
        def __call__(self, fn):
            @functools.wraps(fn)
            def decorated(*args, **kwargs):
                print "In my decorator before call, with arg %s" % self.arg
                result = fn(*args, **kwargs)
                print "In my decorator after call, with arg %s" % self.arg
                return result
            return decorated
    
    关于使用这种装饰器时发生的情况的一些解释:
    @MyDecorator("some other func!")
    def some_other_function():
        print "in some other function!"
    
    第一行创建MyDecorator实例,并将"some other func!"作为参数传递给__init__()。我们将此实例称为my_decorator。接下来,创建未修饰的函数对象(我们称为bare_func)并将其传递给装饰器实例,以便执行my_decorator(bare_func)。这将调用MyDecorator.__call__(),后者将创建并返回包装器函数。最后,将此包装函数分配给名称some_other_function

    关于python - 具有可装饰方法或函数的参数的基于Python类的装饰器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9416947/

  • 10-10 09:57