基于Python的类装饰与可以装饰方法或函数的参数 [英] Python Class Based Decorator with parameters that can decorate a method or a function

查看:126
本文介绍了基于Python的类装饰与可以装饰方法或函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我见过的Python的装饰的例子很多:

I've seen many examples of Python decorators that are:


  • 功能风格装饰(包装功能)

  • 类风格的装饰(实施 __的init __ __获取__ __调用__

  • 不带参数的装饰

  • 的接受参数装饰

  • 装饰这是友好的方法(即可以装点在一个类的方法)

  • 装饰这是功能型(可以装饰一个普通的功能

  • 装饰,可装饰两种方法和功能

不过,我从来没有见过一个例子,可以做到以上,而我无法从各种特定问题的答案(如<一个合成href=\"http://stackoverflow.com/questions/1288498/using-the-same-decorator-with-arguments-with-functions-and-methods\">this 之一,<一个href=\"http://stackoverflow.com/questions/2365701/decorating-python-class-methods-how-do-i-pass-the-instance-to-the-decorator\">this 之一,或这一个(其中有我见过的SO的最佳答案之一)),如何结合所有以上。

But I've never seen a single example which can do all of the above, and I'm having trouble synthesizing from various answers to specific questions (such as this one, this one, or this one (which has one of the best answers I've ever seen on SO)), how to combine all of the above.

我要的是一个的类为主的 的装饰,可装饰的 无论是方法或函数 的,和 这至少需要一个额外的参数 的。也就是说,这样下将工作:

What I want is a class-based decorator which can decorate either a method or a function, and that takes at least one additional parameter. Ie so that the following would work:

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

if it matters, I'm using Python 2.7.

推荐答案

您不需要使用描述符浪费时间。这足以创建 __ __通话()方法中的包装函数并返回。标准Python函数总是可以充当任何方法或函数,根据上下文:

You don't need to mess around with descriptors. It's enough to create a wrapper function inside the __call__() method and return it. Standard Python functions can always act as either a method or a function, depending on context:

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
            fn(*args, **kwargs)
            print "In my decorator after call, with arg %s" % self.arg
        return decorated

中正在发生的事情时,这个装饰用这样的解释了一下:

A bit of explanation about what's going on when this decorator is used like this:

@MyDecorator("some other func!")
def some_other_function():
    print "in some other function!"

第一行创建 MyDecorator 的一个实例,并将其他一些FUNC!作为参数传递给 __ __的init()。让我们把这种情况下 my_decorator 。接下来,未修饰的函数对象 - 姑且称之为 bare_func - 创建并传递给装饰实例,因此 my_decorator(bare_func)被执行。这将调用 MyDecorator .__调用__(),这将创建并返回一个包装函数。最后这个包装功能被分配到名称 some_other_function

The first line creates an instance of MyDecorator and passes "some other func!" as an argument to __init__(). Let's call this instance my_decorator. Next, the undecorated function object -- let's call it bare_func -- is created and passed to the decorator instance, so my_decorator(bare_func) is executed. This will invoke MyDecorator.__call__(), which will create and return a wrapper function. Finally this wrapper function is assigned to the name some_other_function.

这篇关于基于Python的类装饰与可以装饰方法或函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆