Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

java - Does Python really create all bound method for every new instance?

I am reading about classes in Python (3.4) and from what I understand it seems that every new object has its own bound methods instances.

class A:

    def __init__(self, name):
        self.name = name

    def foo(self):
        print(self.name)

a = A('One')
b = A('Two')

print(a.foo ==  b.foo)

The output of this is False.

This seems to me as a waste of memory. I thought that internally a.foo and b.foo would point somehow internally to one function in memory: A.foo where self as the class instance will be passed.

I assume this maybe cannot be implemented easily in the language.

Does each new instance contain also new instances of its bound methods?

If so, does not this hurt the performance or make case for creating new objects more cautiously than in other languages where methods are "shared" among objects like in Java?

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

Methods are bound on demand, each time you access one.

Accessing the name of a function invokes the descriptor protocol, which on function objects returns a bound method.

A bound method is a thin wrapper around a function object; it stores a reference to the original function and to the instance. When calling a method object, it in turn passes the call to the function, with instance inserted as a first argument.

Methods are not created when the instance is created, so there is no extra memory required a-priori.

You can re-create the steps manually:

>>> class A:
...     def __init__(self, name):
...         self.name = name
...     def foo(self):
...         print(self.name)
... 
>>> a = A('One')
>>> a.foo
<bound method A.foo of <__main__.A object at 0x100a27978>>
>>> a.foo.__self__
<__main__.A object at 0x100a27978>
>>> a.foo.__func__
<function A.foo at 0x100a22598>
>>> A.__dict__['foo']
<function A.foo at 0x100a22598>
>>> A.__dict__['foo'].__get__(a, A)
<bound method A.foo of <__main__.A object at 0x100a27978>>
>>> A.__dict__['foo'].__get__(a, A)()
One

It is only the method object that is recreated each time; the underlying function remains stable:

>>> a.foo is a.foo
False
>>> b = A('Two')
>>> b.foo is a.foo
False
>>> b.foo.__func__ is a.foo.__func__
True

This architecture also makes classmethod, staticmethod, and property objects work. You can create your own descriptors, creating a whole host of interesting binding behaviours.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...