In Java, objects are instantiated with a complete copy of the functions from the class linked to them. This is one of the reasons that the Spring Framework has been so successful. Spring helps you cut down on the memory that the Java VM uses if you create many temporary data objects, and other service objects that are served up by Spring as singletons that effectively carry all the functions.
I was just wondering if this true in Python? It seems like it isn't. But that means that if you mess with dict for an object, you are changing all that function for all copies of that class, right?
For example:
class MyObj:
a = 23
def __init__(self, b):
self.b = b
def __add__(self, c):
return self.b + c
If I create an array of MyObj
, is there one instantiation of __add__
for each, or just one for all of them?
There is just one instance of the function, which is stored inside the class. The function gets called with a reference to a class instance as the first argument, which is traditionally called self
.
So, here are three equivalent ways to call the .__add__()
method function:
>>> x = MyObj(2)
>>> MyObj.__add__(x, 3) # we pass in a reference to x explicitly
5
>>> x.__add__(3) # method call implicitly passes reference to x
5
>>> x + 3 # overloaded operator implicitly passes reference to x
5
Also, in Python, the "type signature" of a function is not part of the function's name. The only .__add__()
method you get is the one you declared. In Python you would simply write your code to make the one function do all the different jobs you might want it to do. For example, if you wanted .__add__()
to convert a string into an integer to make x + "3"
return 5, you would do it like so:
class MyObj(object): # see note 0
a = 23
def __init__(self, b):
self.b = b
def __add__(self, other):
return self.b + int(other) # see note 1
def a_add(self, other):
return MyObj.a + other
Note 0: It is best to declare your class as inheriting from object
. In Python 3.x, your class will inherit from object
whether you declare it this way or not, but in Python 2.x you will get an "old-style class" unless you declare it with (object)
after the class name.
Note 1: we don't bother to check the type of the other
argument; we just try to coerce it to an int
value. This is "Duck Typing" in action. Now not only will a string be coerced to an integer, but anything that can successfully be coerced to an int
will work.
Sometimes, to make one function do multiple jobs, you may need extra arguments. You can make them optional so that you don't need to specify them every time you call the function. You can read more about this in a Python tutorial; here's one place: http://diveintopython.net/power_of_introspection/optional_arguments.html
Finally, in Python, you need to explicitly use MyObj.a
to refer to that class variable a
. If you just use a
in a member function, you will get the usual name resolution rules, which will look in the global namespace; the object namespace isn't special.
You could also get to a class variable like so:
def a_add(self, other):
cls = type(self) # cls will be set to the class
return cls.a + other
But this will only work if it is a new-style class that inherits from object
!
Java does not create a new function for each instance. In fact, Java has no function objects to begin with.
Python on the other hand has first class functions. Getting a function object from a instance of a class wraps the class function in a simple object called a bound method
. When a bound method
is invoked, the underlaying class function is called with the instance object as the first argument.
You could say that given this object
class Obj:
def f(self):
print self
o = Obj()
when you do
f = o.f # bound method
under the hood this happens
import types
_func = Obj.__dict__['f'] # get the raw function
f = types.MethodType(_func, o, Obj) # create a "bound method"
As you can see, for each instance of Obj
both _func
and Obj
remain the same, the only thing different is the instance used.
Try this:
>>> o.f
<bound method Obj.f of <__main__.Obj instance at 0x0222CAD0>>
>>> Obj.f
<unbound method Obj.f>
>>> o.f() # this is equivalent to:
>>> Obj.f(o)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With