EDIT2:
A minimal demonstration is:
code = """\
a=1
def f1():
print(a)
print(f1.__closure__)
f1()
"""
def foo():
exec(code)
foo()
Which gives:
None
Traceback (most recent call last):
File "D:/workfiles/test_eval_rec.py", line 221, in <module>
foo()
File "D:/workfiles//test_eval_rec.py", line 219, in foo
exec(code)
File "<string>", line 5, in <module>
File "<string>", line 3, in f1
NameError: name 'a' is not defined
It can be seen that the __closure__ attribute of function defined inside code str passed to exec() is None, making calling the function fails.
Why does this happen and how can I define a function successfully?
I find several questions that may be related.
Closure lost during callback defined in exec()
Using exec() with recursive functions
Why exec() works differently when invoked inside of function and how to avoid it
Why are closures broken within exec?
NameError: name 'self' is not defined IN EXEC/EVAL
These questions are all related to "defining a function insdie exec()". I think the fourth question here is closest to the essence of these problems. The common cause of these problems is that when defining a function in exec(), the __closure__ attribute of the function object can not be set correctly and will always be None. However, many existing answers to this question didn't realize this point.
Why these questions are caused by wrong __closure__:
When defining a function, __closure__ attribute is set to a dict that contains all local symbols (at the place where the keyword def is used) that is used inside the newly defined funtion. When calling a function, local symbol tables will be retrived from the __closure__ attribute. Since the __closure__ is set to None, the local symbol tables can not be retrived as expected, making the function call fail.
These answers work by making None a correct __closure__ attribute:
Existing solutions to the questions listed above solve these problems by getting the function definition rid of the usage of local symbol, i.e, they make the local symbols used(variable, function definition) global by passing globals() as locals of exec or by using keyword global explicitly in the code string.
Why existing solution unsatisfying:
These solutions I think is just an escape of the core problem of setting __closure__ correctly when define a functioni inside exec(). And as symbols used in the function definition is made global, these solutions will produce redundant global symbol which I don't want.
Original Questions:
(You May ignore this session, I have figured something out, and what I currently want to ask is described as the session EDIT2. The original question can be viewed as a sepecial case of the question described in session EDIT2)
original title of this question is: Wrapping class function to new function with exec() raise NameError that ‘self’ is not defined
I want to wrap an existing member function to a new class function. However, exec() function failed with a NameError that ‘self’ is not defined.
I did some experiment with the following codes. I called globals() and locals() in the execed string, it seems that the locals() is different in the function definition scope when exec() is executed. "self" is in the locals() when in exec(), however, in the function definition scope inside the exec(), "self" is not in the locals().
class test_wrapper_function():
def __init__(self):
# first wrapper
def temp_func():
print("locals() inside the function definition without exec:")
print(locals())
return self.func()
print("locals() outside the function definition without exec:")
print(locals())
self.wrappered_func1 = temp_func
# third wrapper using eval
define_function_str = '''def temp_func():
print("locals() inside the function definition:")
print(locals())
print("globals() inside the function definition:")
print(globals())
return self.func()
print("locals() outside the function definition:")
print(locals())
print("globals() outside the function definition:")
print(globals())
self.wrappered_func2 = temp_func'''
exec(define_function_str)
# call locals() here, it will contains temp_func
def func(self):
print("hi!")
t = test_wrapper_function()
print("**********************************************")
t.wrappered_func1()
t.wrappered_func2()
I have read this link. In the exec(), memeber function, attribute of "self" can be accessed without problem, while in the function difinition in the exec(), "self" is not available any more. Why does this happen?
Why I want to do this:
I am building a PyQt program. I want to create several similar slots(). These slots can be generated by calling one member function with different arguments. I decided to generate these slots using exec() function of python. I also searched with the keyword "nested name scope in python exec", I found this question may be related, but there is no useful answer.
To be more specific. I want to define a family of slots like func_X (X can be 'a', 'b', 'c'...), each do something like self.do_something_on(X). Here, do_something is a member function of my QWidget. So I use a for loop to create these slots function. I used codes like this:
class MyWidget():
def __init__(self):
self.create_slots_family()
def do_something(self, character):
# in fact, this function is much more complex. Do some simplification.
print(character)
def create_slots_i(self, character):
# want to define a function like this:
# if character is 'C', define self.func_C such that self.func_C() works like self.do_something(C)
create_slot_command_str = "self.func_" + character + " = lambda:self.do_something('" + character + "')"
print(create_slot_command_str)
exec(create_slot_command_str)
def create_slots_family(self):
for c in ["A", "B", "C", "D"]:
self.create_slots_i(c)
my_widget = MyWidget()
my_widget.func_A()
Note that, as far as I know, the Qt slots should not accept any parameter, so I have to wrap self.do_something(character) to be a series function self.func_A, self.func_C and so on for all the possible characters.
So the above is what I want to do orignially.
EDIT1:
(You May ignore this session, I have figured something out, and what I currently want to ask is described as the session EDIT2. This simplified version of original question can also be viewed as a sepecial case of the question described in session EDIT2)
As #Mad Physicist suggested. I provide a simplified version here, deleting some codes used for experiments.
class test_wrapper_function():
def __init__(self):
define_function_str = '''\
def temp_func():
return self.func()
self.wrappered_func2 = temp_func'''
exec(define_function_str)
def func(self):
print("hi!")
t = test_wrapper_function()
t.wrappered_func2()
I expected this to print a "hi". However, I got the following exception:
Traceback (most recent call last):
File "D:/workfiles/test_eval_class4.py", line 12, in <module>
t.wrappered_func2()
File "<string>", line 2, in temp_func
NameError: name 'self' is not defined
Using Exec
You've already covered most of the problems and workarounds with exec, but I feel that there is still value in adding a summary.
The key issue is that exec only knows about globals and locals, but not about free variables and the non-local namespace. That is why the docs say
If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
There is no way to make it run as though it were in a method body. However, as you've already noted, you can make exec create a closure and use that instead of the internal namespace by adding a method body to your snippet. However, there are still a couple of subtle restrictions there.
Your example of what you are trying to do showcases the issues perfectly, so I will use a modified version of that. The goal is to make a method that binds to self and has a variable argument in the exec string.
class Test:
def create_slots_i(self, c):
create_slot_command_str = f"self.func_{c} = lambda: self.do_something('{c}')"
exec(create_slot_command_str)
def do_something(self, c):
print(f'I did {c}!')
There are different ways of getting exec to "see" variables: literals, globals, and internal closures.
Literals. This works robustly, but only for simple types that can be easily instantiated from a string. The usage of c above is a perfect example. This will not help you with a complex object like self:
>>> t = Test()
>>> t.create_slots_i('a')
>>> t.func_a()
...
NameError: name 'self' is not defined
This happens exactly because exec has no concept of free variables. Since self is passed to it via the default locals(), it does not bind the reference to a closure.
globals. You can pass in a name self to exec via globals. There are a couple of ways of doing this, each with its own issues. Remember that globals are accessed by a function through its __globals__ (look at the table under "Callable types") attribute. Normally __globals__ refers to the __dict__ of the module in which a function is defined. In exec, this is the case by default as well, since that's what globals() returns.
Add to globals: You can create a global variable named self, which will make your problem go away, sort of:
>>> self = t
>>> t.func_a()
I did a!
But of course this is a house of cards that falls apart as soon as you delete, self, modify it, or try to run this on multiple instances:
>>> del self
>>> t.func_a()
...
NameError: name 'self' is not defined
Copy globals. A much more versatile solution, on the surface of it, is to copy globals() when you run exec in create_slots_i:
def create_slots_i(self, c):
create_slot_command_str = f"self.func_{c} = lambda: self.do_something('{c}')"
g = globals().copy()
g['self'] = self
exec(create_slot_command_str, g)
This appears to work normally, and for a very limited set of cases, it actually does:
>>> t = Test()
>>> t.create_slots_i('a')
>>> t.func_a()
I did a!
But now, your function's __globals__ attribute is no longer bound to the module you created it in. If it uses any other global values, especially ones that might change, you will not be able to see the changes. For limited functionality, this is OK, but in the general case, it can be a severe handicap.
Internal Closures. This is the solution you already hit upon, where you create a closure within the exec string to let it know that you have a free variable by artificial means. For example:
class Test:
def create_slots_i(self, c):
create_slot_command_str = f"""def make_func(self):
def func_{c}():
self.do_something('{c}')
return func_{c}
self.func_{c} = make_func(self)"""
g = globals().copy()
g['self'] = self
exec(create_slot_command_str, g)
def do_something(self, c):
print(f'I did {c}!')
This approach works completely:
>>> t = Test()
>>> t.create_slots_i('a')
>>> t.func_a()
I did a!
The only real drawbacks here are security, which is always a problem with exec, and the sheer awkwardness of this monstrosity.
A Better Way
Since you are already creating closures, there is really no need to use exec at all. In fact, the only thing you are really doing is creating methods so that self.func_... will bind the method for you, since you need a function with the signature of your slot and access to self. You can write a simple method that will generate functions that you can assign to your slots directly. The advantage of doing it this way is that (a) you avoid calling exec entirely, and (b) you don't need to have a bunch of similarly named auto-generated methods polluting your class namespace. The slot generator would look something like this:
def create_slots_i(self, c):
def slot_func():
self.do_something(c) # This is a real closure now
slot_func.__name__ = f'func_{c}'
return slot_func
Since you will not be referring to these function objects anywhere except your slots, __name__ is the only way to get the "name" under which they were stored. That is the same thing that def does for you under the hood.
You can now assign slots directly:
some_widget.some_signal.connect(self.create_slots_i('a'))
Note
I originally had a more complex approach in mind for you, since I thought you cared about generating bound methods, instead of just setting __name__. In case you have a sufficiently complex scenario where it still applies, here is my original blurb:
A quick recap of the descriptor protocol: when you bind a function with the dot operator, e.g., t.func_a, python looks at the class for descriptors with that name. If your class has a data descriptor (like property, but not functions), then that descriptor will shadow anything you may have placed in the instance __dict__. However, if you have a non-data descriptor (one a __get__ method but without a __set__ method, like a function object), then it will only be bound if an instance attribute does not shadow it. Once this decision has been made, actually invoking the descriptor protocol involves calling type(t).func_a.__get__(t). That's how a bound method knows about self.
Now you can return a bound method from within your generator:
def create_slots_i(self, c):
def slot_func(self):
self.do_something(c) # This is a closure on `c`, but not on `self` until you bind it
slot_func.__name__ = f'func_{c}'
return slot_func.__get__(self)
Why this phenomena happen:
Actually the answer of the question 4 listed above can answer this question.
When call exec() on one code string, the code string is first compiled. I suppose that during compiling, the provided globals and locals is not considered. The symbol in the exec()ed code str is compiled to be in the globals. So the function defined in the code str will be considered using global variables, and thus __closure__ is set to None.
Refer to this answer for more information about what the func exec does.
How to deal with this phenomena:
Imitating the solutions provided in the previous questions, for the minimal demostration the question, it can also be modified this way to work:
a=1 # moving out of the variable 'code'
code = """\
def f1():
print(a)
print(f1.__closure__)
f1()
"""
def foo():
exec(code)
foo()
Although the __closure__ is still None, the exception can be avoided because now only the global symbol is needed and __closure__ should also be None if correctly set. You can read the part The reason why the solutions work in the question body for more information.
This was originally added in Revision 4 of the question.
TL;DR
To set correct __closure__ attribute of function defined in the code string passed to exec() function. Just wrap the total code string with a function definition.
I provide an example here to demonstrate all possible situations. Suppose you want to define a function named foo inside a code string used by exec(). The foo use function, variables that defined inside and outside the code string:
def f1():
outside_local_variable = "this is local variable defined outside code str"
def outside_local_function():
print("this is function defined outside code str")
code = """\
local_variable = "this is local variable defined inside code str"
def local_function():
print("this is function defined inside code str")
def foo():
print(local_variable)
local_function()
print(outside_local_variable)
outside_local_function()
foo()
"""
exec(code)
f1()
It can be wrapper like this:
def f1():
outside_local_variable = "this is local variable defined outside code str"
def outside_local_function():
print("this is function defined outside code str")
code = """\
def closure_helper_func(outside_local_variable, outside_local_function):
local_variable = "this is local variable defined inside code str"
def local_function():
print("this is function defined inside code str")
def foo():
print(local_variable)
local_function()
print(outside_local_variable)
outside_local_function()
foo()
closure_helper_func(outside_local_variable, outside_local_function)
"""
exec(code)
f1()
Detailed explanation:
Why the __closure__ attribute is not corretly set:
please refer to The community wiki answer.
How to set the __closure__ attribute to what's expected:
Just wrap the whole code str with a helper function definition and call the helper function once, then during compiling, the variables are considered to be local, and will be stored in the __closure__ attribute.
For the minimal demonstration in the question, it can be modified to following:
code = """\
def closure_helper_func():
a=1
def f1():
print(a)
print(f1.__closure__)
f1()
closure_helper_func()
"""
def foo():
exec(code)
foo()
This output as expected
(<cell at 0x0000019CE6239A98: int object at 0x00007FFF42BFA1A0>,)
1
The example above provide a way to add symbols that defined in the code str to the __closure__ For example, in the minimal demo, a=1 is a defined inside the code str. But what if one want to add the local symbols defined outside the code str? For example, in the code snippet in EDIT1 session, the self symbol needs to be added to the __closure__, and the symbol is provided in the locals() when exec() is called. Just add the name of these symbols to the arguments of helper function and you can handle this situation.
The following shows how to fix the problem in EDIT1 session.
class test_wrapper_function():
def __init__(self):
define_function_str = '''\
def closure_helper_func(self):
def temp_func():
return self.func()
self.wrappered_func2 = temp_func
closure_helper_func(self)
'''
exec(define_function_str)
def func(self):
print("hi!")
t = test_wrapper_function()
t.wrappered_func2()
The following shows how to fix the codes in the session "Why I want to do this"
class MyWidget():
def __init__(self):
self.create_slots_family()
def do_something(self, character):
# in fact, this function is much more complex. Do some simplification.
print(character)
def create_slots_i(self, character):
# want to define a function like this:
# if character is 'C', define self.func_C such that self.func_C() works like self.do_something(C)
# create_slot_command_str = "self.func_" + character + " = lambda:self.do_something('" + character + "')"
create_slot_command_str = """
def closure_helper_func(self):
self.func_""" + character + " = lambda:self.do_something('" + character + """')
closure_helper_func(self)
"""
# print(create_slot_command_str)
exec(create_slot_command_str)
def create_slots_family(self):
for c in ["A", "B", "C", "D"]:
self.create_slots_i(c)
my_widget = MyWidget()
my_widget.func_A()
This solution seems to be too tricky. However, I can not find a more elegant way to declare that some variables should be local symbol during compiling.
I am new to the more advanced features of Python like decorators.
I am unable to understand how the Python interpreter actually understands where to put the original function object in a decorator.
Lets look at an example: Examples taken from here.
Simple decorator with no arguments:
def call_counter(func):
def helper(*args, **kwargs):
helper.calls += 1
return func(*args, **kwargs)
helper.calls = 0
return helper
#call_counter
def succ(x):
return x + 1
This makes perfect sense if we can assume that the first/only argument to the decorator call_counter(func) is the function object that needs to wrapped ie. in this case succ() function.
But things become inconsistent when you are talking about "decorators with parameters". Look at the example below:
Decorator with one argument:
def greeting(expr): # Shouldn't expr be the function here ? Or at least isn't there suppose to be another parameter.
def greeting_decorator(func): # How does Python know to pass the function down here ?
def function_wrapper(x):
print(expr + ", " + func.__name__ + " returns:")
func(x)
return function_wrapper
return greeting_decorator
#greeting("Hello")
def foo(x):
print(42)
foo("Hi")
Now we know Python has no concept of data-types, so function parameters give no information about what type of object they will contain.
Am I correct ?
Having said that lets look at the line from the above example:
def greeting(expr):
If for decorators the first argument is the function to be wrapped then by that logic expr should point to foo() right ? Otherwise there should be at least two parameters in greeting(), like:
def greeting(func, expr):
But instead Python can "magically" understand that the inner function needs to be passed the function reference:
def greeting(expr):
def greeting_decorator(func): # How is it correctly put one level down ?
The code has no datatypes or type information specified, so how is it that for decorators without arguments the function is passed as the first argument and for decorators with arguments the function is passed to the inner function ?
How can the interpreter detect that ?
What is going on here ?
This seems like "magic" to me.
What happens if I have 5 or 6 levels of nested functions ?
I am pretty sure I am missing something pretty basic here.
Thanks.
Python evaluates the expression after the # and uses the result as the decorator function.
Python calls the __call__ method of the object that is the decorator with the function as argument.
using
#call_counter
def succ(x):
return x + 1
callcounter is the object looked for __call__ to give the argument func
If you use
#greeting("Hello")
def foo(x):
print(42)
greeting("Hello") is evaluated and its result is an object that Python uses the __call__ method with the func argument.
I learned that we can equate one function with another in Python like this:
def func_1(x)
print("func_1")
print(x)
def func_2(x)
print("func_2")
print(x)
func_1 =func_2
So here what is happening is every call to func_1 executes func_2.
However, I read about decorators and the following is a simple code illustrating them:
def our_decorator(func):
def function_wrapper(x):
print("Before calling " + func.__name__)
func(x)
print("After calling " + func.__name__)
return function_wrapper
def foo(x):
print("Hi, foo has been called with " + str(x))
print("We call foo before decoration:")
foo("Hi")
print("We now decorate foo with f:")
foo = our_decorator(foo)
print("We call foo after decoration:")
foo(42)
Here as we can see in the following line:
foo = our_decorator(foo)
something like the previous function equation is taking place . I thought this is how decorators might be working, i.e., replacing call to the decoratee by call to decorator .
However, under this impression if I write up a code like the following:
def our_decorator():
def function_wrapper(x):
print("Before calling " )
foo(x)
print("After calling " )
return function_wrapper
def foo(x):
print("Hi, foo has been called with " + str(x))
print("We call foo before decoration:")
foo("Hi")
print("We now decorate foo with f:")
foo = our_decorator()
print("We call foo after decoration:")
foo(42)
The above results in infinite recursion printing infinite number of "Before calling ".
So, I could conclude that a decorator must be something which takes a function as an argument.
So the equating of functions differ in these two cae, namely equating with function which takes another function as an argument, and equating two functions which don't take another function as argument.
How might this two differing in internal implementation?
What you call "equating functions" is really just a variable assignment. A function definition (with def) creates a function and assigns it to a variable name. After you do func_1 = func_2, you have 2 variables referring to the same function.
What happens in your decorator examples is a natural consequence of the previous paragraph. Leave a comment if you need further clarification on that.
I hope your question can be answered by explaining few terms.
You are using the term "equating" for what it is commonly called "assigning". name = expr is an assignment statement. The name name is given (assigned) to the object which is the result of the expression expr.
In Python functions are not treated special. This is sometimes expressed with the sentence "functions are first class objects" and basically it means that function objects can be assigned to variables (names), passed as arguments etc. the same way as numbers, strings and other objects.
A (function) decorator processes another function. It is a function that takes the function to be decorated as its argument and returns a "decorated" (i.e. enhanced or modifed in some way) version of it. Sometimes it only registers the function e.g. as a handler or as a part of an API and returns it unchanged. There is a special syntax for it:
#decorator
def func(...):
pass
which is equivalent to:
func = decorator(func)
and also:
#decorator(args)
def func(...):
pass
which is equivalent to:
_real_decorator = decorator(args)
func = _real_decorator(func)
Because this #decorator syntax is so simple to use and easy to read, you normally don't write:
func = decorator(func)
To summarize:
func1 = some_func is plain assignment, giving other name to some_func.
func2 = create_function() this would be called a function factory in some languages. You wrote that in your question.
func = decorate_function(func) this is a decoration of func
Note: there exist class decorators, they are very similar, but enhance class definitions instead of functions.
A decorator looks like this:
def decorator_with_args(*args, **kwargs):
def wrapper(f: "the function being decorated"):
def wrapped(*args, **kwargs):
# inside here is the code that is actually executed
# when calling the decorated function. This should
# always include...
f(*args, **kwargs)
# and usually return its result
return wrapped
return wrapper
# or
def decorator_without_args(f: "the function being decorated"):
def wrapped(*args, **kwargs):
# as above
return f(*args, **kwargs)
return wrapped
and is used by:
#decorator_with_args("some", "args")
def foo(x):
print("foo:", x) # or whatever
#decorator_without_args
def bar(x):
print("bar:", x)
This is equivalent to defining each function without the #decorator... magic and applying the decorator afterwards
def baz(x):
print("baz:", x)
baz = decorator_with_args("some", "arguments")(baz)
# or
baz = decorator_without_args(baz)
In your example code you call foo inside your decorator, then you decorate foo with that decorator, so you end up recursing infinitely. Every time you call foo, it runs your decorator code which also invokes foo. Every time your decorator invokes foo, it runs your decorator code which also invokes foo. Every time your decorator's decorator invokes foo, is runs your decorator code which also... etc
I was wondering why the following works:
def wrapper():
def wrap(p=10):
def f():
print(p)
f()
return wrap
f2 = wrapper()
f2()
But this doesn't:
def f():
print(p)
def enhance(f):
def wrap(p=10):
f()
return wrap
f2 = enhance(f)
f2() # NameError: name 'p' is not defined
Is there a way I can modify the second scenario so that variable p is defined? I was playing around with function decorators but couldn't figure it out how to expose the variables to the function I'm passing into the decorators.
I think I understand what you are really asking. You're taking about decorators, not variable scope. You say you can't figure out how to "expose the variables to the function I'm passing to the decorators." In your case 2, the function you are passing to enhance doesn't have any variables (arguments). Suppose we give it an argument, like this:
def f(p):
print(p)
def enhance(f):
def wrap(p=10):
f(p) # pass the argument to f
return wrap
f2 = enhance(f)
f2()
Now you have a function, named enhance, which can be used as a decorator. The function to be decorated takes one argument. The decorator will replace this function with a new function, which can be called with one or zero arguments. If called with no arguments it will get the value "10" as a default.
Decorators replace one function with another function. In general it isn't the decorator's job to supply the arguments, except in the case of default arguments as you are trying to do. The arguments come from the code that calls the function.
because in example 2 you’re referencing p that is not defined in one function and used as a parameter in the other function each of which is defined in their own scope.
in example 1 a function defined within the scope of another ie a nested function, has access to the outer functions scope (and therefore its variables)
[Updated]: Answer inline below question
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
Then on 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 on what's going wrong, and if it is possible for #decorate to correctly infer that test_call is a method?
[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'.
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'
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
No, this is not possible as you have requested, because there is no inherent difference between bound methods and functions. A method is simply a function wrapped up to get the calling instance as the first argument (using Python descriptors).
A call like:
Test.test_call
which returns an unbound method, translates to
Test.__dict__[ 'test_call' ].__get__( None, spam )
which is an unbound method, even though
Test.__dict__[ 'test_call' ]
is a function. This is because functions are descriptors whose __get__ methods return methods; when Python sees one of these in the lookup chain it calls the __get__ method instead of continuing up the chain.
In effect, the 'bound-methodiness' of a function is determined at runtime, not at define-time!
The decorator simply sees the function as it is defined, without looking it up in a __dict__, so cannot tell whether it is looking at a bound method.
It might be possible to do this with a class decorator that modifies __getattribute__, but that's a particularly nasty hack. Why must you have this functionality? Surely, since you have to place the decorator on the function yourself, you could pass it an argument that says whether said function is defined within a class?
class Test:
#decorate( method = True )
def test_call:
...
#decorate( method = False )
def test_call:
...
Your decorator is run before the function becomes a method. def keyword inside a class defines a function line in any other place, then the functions defined in the body of a class are added to the class as methods. Decorator operates on the function before it is processed by the class that is why your code 'fails'.
There is no way for the #decorate to see the function is actually a method. A workaround for that would be to decorate the function whatever it is (e.g. adding an attribute do_something_about_me_if_I_am_a_method ;-)) and then process it again after the class is computed (iterating over the class members and doing whatever you want with those decorated).
I tried a slightly different example, with one decorated method and one undecorated method.
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
Then the output is:
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>
Thus, the decorator saw a different type than the main function did, but the decorator did not change the function's type, or it would be different from the undecorated function.