Change the status of a decorator function from method to function

[Updated]: answer in the line below the question

I have a validation program, and one goal is for the logic in the decorator to know if the function that it decorates is a class method or a regular function. This is strange. The following is the code 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

Then at execution:

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

Any clue about what is going wrong, and if it is possible that @decorate is correctly inferring that test_call is a method?

[Answer] The answer of carl below is almost perfect. I had a problem using a decorator in a method that calls subclasses. I adapted his code to enable 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
+5
source share
4

, , , , "" "".

, , , "" . , Python :

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

, , , , . CPython 2.6, promises. , , .

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
+5

, , , . - , , ( Python ).

:

Test.test_call

,

Test.__dict__[ 'test_call' ].__get__( None, spam )

,

Test.__dict__[ 'test_call' ]

- . , - , __get__; Python , __get__ .

, " " , !

, , __dict__, , .


, , __getattribute__, . ? , , , , ?

class Test:
    @decorate( method = True )
    def test_call:
        ...

@decorate( method = False )
def test_call:
    ...
+3

, . def , , , . , " ".

, @decorate , . , , (, do_something_about_me_if_I_am_a_method ;-)), ( , ).

+1

: .

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

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

if __name__ == '__main__':
  print 'main thinks function is', Test.test_call
  print 'main thinks function 2 is', Test.test_call_2

:

decorator thinks function is <function test_call at 0x100426b18>
main thinks function is <unbound method Test.test_call>
main thinks function 2 is <unbound method Test.test_call_2>

, , , , .

0

All Articles