Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
86 views
in Technique[技术] by (71.8m points)

python - Why is a method not identical to itself?

The Python documentation about the is operator says:

The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.

Let's try that:

>>> def m():
...   pass
... 
>>> m is m
True

The Python documentation also says:

Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the is operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info.

>>> class C:
...   def m():
...     pass
... 
>>> C.m is C.m
False

I searched for more explanations, but I was not able to find any.

Why is C.m is C.m false?

I am using Python 2.x. As noted in the answers below, in Python 3.x C.m is C.m is true.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you ask for an attribute of an instance which is a function, you get a bound method: a callable object which wraps the function defined in the class and passes the instance as the first argument. In Python 2.x, when you ask for an attribute of a class which is a function you get a similar proxy object called an unbound method:

>>> class A: m = lambda: None
...
>>> A.m
<unbound method A.<lambda>>

This special object is created when you ask for it, and not apparently cached anywhere. That means that when you do

>>> A.m is A.m
False

you are creating two distinct unbound method objects and testing them for identity.

Notice that

>>> x = A.m
>>> x is x
True

and

>>> A.m.im_func is A.m.im_func
True

work fine. (im_func is the original function which the unbound method object is wrapping.)

In Python 3.x, incidentally, C.m is C.m is True, because the (somewhat pointless) unbound method proxy objects were removed entirely and you just get the original function which you defined.


This is just one example of the very dynamic nature of attribute lookup in Python: when you ask for an attribute of an object, it is possible to run arbitrary Python to calculate the value of that attribute. Here's another example where your test fails in which it is much clearer why:

>>> class ChangingAttribute(object):
...     @property
...     def n(self):
...             self._n += 1
...             return self._n
...
...     def __init__(self):
...             self._n = 0
...
>>> foo = ChangingAttribute()
>>> foo.n
1
>>> foo.n
2
>>> foo.n
3
>>> foo.n is foo.n
False
>>> foo.n
6

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...