开发者

Python instancemethods & decorators

开发者 https://www.devze.com 2023-03-15 17:29 出处:网络
I\'ve got the following pro开发者_Python百科blem: I need to write a decorator that would be able to detect a situation where it is used around a method and around a regular function.

I've got the following pro开发者_Python百科blem:

I need to write a decorator that would be able to detect a situation where it is used around a method and around a regular function.

So let's consider the following code:

def somedecorator(fn):
    print "decorating function:", fn
    print "function class:", fn.__class__
    return fn

@somedecorator
def regular_func():
    print "I'm a regular function"

class SomeClass(object):

    @somedecorator
    def class_method(self):
        print "I'm a class method"

The output reads:

decorating function: <function regular_func at 0x181d398>
function class: <type 'function'>
decorating function: <function class_method at 0x181d410>
function class: <type 'function'>

However writing:

print regular_func
print SomeClass.class_method
print SomeClass().class_method

Produces output:

<function regular_func at 0x181d398>
<unbound method SomeClass.class_method>
<bound method SomeClass.class_method of <__main__.SomeClass object at 0x16d9e50>>

So as it turns out (not so surprisingly) that decorators are applied to functions before they are turned into methods.

Question: What would you suggest to distinguish the two applications from the decorator point of view?

EDIT For the curious ones - I need the described distinction because of pickling. I don't really want to go into details on this one.


May be looking at the stack?

def somedecorator(fn):
    import traceback
    print "decorating function:", fn
    print "function class:", fn.__class__
    print traceback.extract_stack()[-2][2]
    return fn

If the decorator has been called from a module outputs 'module' and from the method outputs 'SomeClass'. If called from inside a function returns also the functions name, so to distingish between both cases, you could lookup locals() and globals() to know what the hell are those names: functions or classes.

What do you think?

Edit: The objects may be out of scope so the globals() and locals() thing wouldn't work...


You can't. A method is a function. Inside the class, there's just a regular function. Instancemethod descriptor magic only happens when an object is instanciated, and the descriptors are part of the object, not part of the class. "Unbound methods" (which btw disappeared in Python 3, for good reasons - they serve about no purpose, are a meaningless concept and add some overhead) are only temporary wrapper objects around those functions, generated whenever the function would be accessed as attribute of the class.

The sanest way to differentiate between a method and a function would be providing two decorators and let the programmers decide which one to apply. Or even better, do away with this strange seperation - methods are functions, nothing special, you should treat them as such.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号