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
276 views
in Technique[技术] by (71.8m points)

python - Two methods inherited from one method in class are different in instances, aren't they?

Can someone please explain why it is so?

class Foo:
    def bar(self):
        pass

a = Foo()
b = Foo()

a.bar == b.bar # False
a.bar is b.bar # False

I thought that they both inherit the class method and it's the one method.

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 access a function through an instance that is defined on the class, a bound-method object is created each time. From the docs:

What exactly happens when a method is called? You may have noticed that x.f() was called without an argument above, even though the function definition for f() specified an argument. What happened to the argument? Surely Python raises an exception when a function that requires an argument is called without any — even if the argument isn’t actually used…

Actually, you may have guessed the answer: the special thing about methods is that the instance object is passed as the first argument of the function. In our example, the call x.f() is exactly equivalent to MyClass.f(x). In general, calling a method with a list of n arguments is equivalent to calling the corresponding function with an argument list that is created by inserting the method’s instance object before the first argument.

If you still don’t understand how methods work, a look at the implementation can perhaps clarify matters. When an instance attribute is referenced that isn’t a data attribute, its class is searched. If the name denotes a valid class attribute that is a function object, a method object is created by packing (pointers to) the instance object and the function object just found together in an abstract object: this is the method object.

Note, this happens every time you access a method:

>>> class Foo:
...    def bar(self): pass
...
>>> f = Foo()
>>> f.bar is f.bar
False

How does this work? Well, actually, functions are descriptor objects, note the presence of a __get__:

>>> def func(): pass
...
>>> func.__get__
<method-wrapper '__get__' of function object at 0x101e38ae8>

In other words, you can think of Python functions as being implemented thusly:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        if obj is None:
            return self
        return types.MethodType(self, obj)

Of course, they aren't implemented in Python (in CPython at least!).

Also note, accessing the function directly on the class, of course, doesn't do this (at least on Python 3, which you've tagged on your question):

>>> Foo.bar is Foo.bar
True

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

...