[Tutor] Are the methods in a class copied or just linked to?
Steven D'Aprano
steve at pearwood.info
Fri Jul 3 03:17:12 CEST 2015
On Thu, Jul 02, 2015 at 12:30:23PM -0700, Jim Mooney Py3.4.3winXP wrote:
> When an instance uses a class method, does it actually use the method that
> is in the class object's memory space, or is the method copied to the
> instance?
The first. And it is not just an implementation detail, it is part of
Python's programming model.
When you define a class in you define methods and other attributes in
the class namespace:
class C:
attr = 23
def method(self, arg):
pass
'attr' and 'method' exist inside C.__dict__. That is, I believe, more
than just implementation, I believe that is considered part of the
language. For instance, this works in IronPython too:
>>> class C:
... def method(self): pass
...
>>> C.__dict__['method']
<function method at 0x000000000000002B>
even though classes in IronPython are based on a completely different
technology (the .Net CLR) from the standard CPython implementation.
When you create an instance, under normal circumstances it gets its own
__dict__, but that does *not* get a copy of the method, nor even a
reference to the original method. In IronPython again:
>>> c = X()
>>> c.__dict__ != C.__dict__ # Separate dictionaries?
True
>>> 'method' in c.__dict__ # in the instance?
False
>>> 'method' in C.__dict__ # in the class?
True
When you call a method, c.method(), Python does a name look-up.
Simplified, it looks in c.__dict__, then C.__dict__, then the __dict__s
of each of C's parents (if any).
The upshot of this is that you can actually override the method for a
specific instance. In Ruby, this technique is called "singleton method",
in Python it doesn't have a standard name, but it can be useful. It only
works on classes with an instance __dict__, so it doesn't work on ints,
floats, strings and other built-in types, and for technical reasons it
doesn't work on magic __dunder__ methods, and it is a little fiddly to
get working, but it does work:
>>> class C:
... def method(self):
... return "shared"
...
>>> c = C()
>>> d = C()
>>> from types import MethodType
>>> c.method = MethodType(lambda self: 'overridden', c)
>>> c.method()
'overridden'
>>> d.method()
'shared'
--
Steve
More information about the Tutor
mailing list