Reputation: 1856
While I'm studying the python attributes and methods, and read to the Example 1.2. A function is more. I try to do a simple test base on the example, but the result makes me a little confused.
>>> class foo(object):
... def fun(self):
... pass
...
>>> f = foo()
>>> f.fun is foo.fun
False
>>> id(f.fun)
36093064
>>> id(foo.fun)
36093064
>>>
python version, 2.7.5 operation sys, win8
Why the 'is' test return False but the id return the same value? I expected to see the difference ids in the beginning. Thanks in advance!
Upvotes: 1
Views: 126
Reputation: 172229
What the id
is is an internal implementation detail. The id
is of little use to use as a programmer. In CPython it tends to be the memory address of the object, the object in this case being a function object.
In this case the object is the same, it's a function. In one case the function is bound to an instance, in the other case it's not. This means that when you call it, in the bound case it will automatically get the instance as the first parameter, and in the second case not.
But it is the same function.
So why does f.fun is foo.fun
return False
?
Because methods compare as not being the same. Even with themselves:
>>> foo.fun is foo.fun
False
>>> f = foo()
>>> f.fun is f.fun
False
This is because these objects are wrappers. If you want to compare methods, compare the im_func attribute:
>>> bar = foo
>>> bar.fun.im_func is foo.fun.im_func
True
>>> f.fun.im_func is foo.fun.im_func
True
In Python 3, the unbound method is gone, and normal functions are used. So in Python 3 you will get:
>>> foo.fun is foo.fun
True
Bound methods still compare as false to themselves:
>>> f.fun is f.fun
False
And you need to compare using the __func__
attribute:
>>> f.fun.__func__ is foo.fun
True
Upvotes: 5