装饰器将功能状态从方法更改为功能 [英] Decorator changing function status from method to function

查看:68
本文介绍了装饰器将功能状态从方法更改为功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[更新]:在问题下面内联

[Updated]: Answer inline below question

我有一个检查程序,一个目的是让装饰器中的逻辑知道它正在装饰的功能是否是一个类方法或常规函数。这以一种奇怪的方式失败了。以下是在Python 2.6中运行的代码:

I have an inspecting program and one objective is for logic in a decorator to know whether the function it is decorating is a class method or regular function. This is failing in a strange way. Below is code run in Python 2.6:

def decorate(f):
    print 'decorator thinks function is', f
    return f

class Test(object):
    @decorate
    def test_call(self):
        pass

if __name__ == '__main__':
    Test().test_call()
    print 'main thinks function is', Test().test_call

然后执行:

decorator thinks function is <function test_call at 0x10041cd70>
main thinks function is <bound method Test.test_call of <__main__.Test object at 0x100425a90>>

关于出问题的任何线索,以及@decorate是否有可能正确推断出test_call是一种方法?

Any clue on what's going wrong, and if it is possible for @decorate to correctly infer that test_call is a method?

[答案]
卡尔在下面的回答几乎是完美的。在子类调用的方法上使用装饰器时,我遇到了问题。我修改了他的代码,以包括对超类成员的im_func比较:

[Answer] carl's answer below is nearly perfect. I had a problem when using the decorator on a method that subclasses call. I adapted his code to include a im_func comparison on superclass members:

ismethod = False
for item in inspect.getmro(type(args[0])):
    for x in inspect.getmembers(item):
        if 'im_func' in dir(x[1]):
            ismethod = x[1].im_func == newf
            if ismethod:
                break
    else:
        continue
    break


推荐答案

就像其他人所说的那样,函数在绑定之前已经被修饰,因此您无法直接确定它是方法还是

As others have said, a function is decorated before it is bound, so you cannot directly determine whether it's a 'method' or 'function'.

一种确定函数是否为方法的合理方法是检查 self是否为第一个参数。虽然不是万无一失,但是大多数Python代码都遵循此约定:

A reasonable way to determine if a function is a method or not is to check whether 'self' is the first parameter. While not foolproof, most Python code adheres to this convention:

import inspect
ismethod = inspect.getargspec(method).args[0] == 'self'






这是一种复杂的方法,似乎可以自动确定该方法是否是绑定方法。在CPython 2.6上仅适用于一些简单的情况,但是没有什么用。


Here's a convoluted way that seems to automatically figure out whether the method is a bound or not. Works for a few simple cases on CPython 2.6, but no promises. It decides a function is a method if the first argument to is an object with the decorated function bound to it.

import inspect

def decorate(f):
    def detect(*args, **kwargs):
        try:
            members = inspect.getmembers(args[0])
            members = (x[1].im_func for x in members if 'im_func' in dir(x[1]))
            ismethod = detect in members
        except:
            ismethod = False
        print ismethod

        return f(*args, **kwargs)
    return detect

@decorate
def foo():
    pass

class bar(object):
    @decorate
    def baz(self):
        pass

foo() # prints False
bar().baz() # prints True

这篇关于装饰器将功能状态从方法更改为功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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