What is the difference between the following class methods?
Is it that one is static and the other is not?
class Test(object):
def method_one(self):
print "Called method_one"
def method_two():
print "Called method_two"
a_test = Test()
a_test.method_one()
a_test.method_two()
that is an error.
first of all, first line should be like this (be careful of capitals)
Whenever you call a method of a class, it gets itself as the first argument (hence the name self) and method_two gives this error
The call to method_two will throw an exception for not accepting the self parameter the Python runtime will automatically pass it.
If you want to create a static method in a Python class, decorate it with the
staticmethod decorator
.Accurate explanation from Armin Ronacher above, expanding on his answers so that beginners like me understand it well:
Difference in the methods defined in a class, whether static or instance method(there is yet another type - class method - not discussed here so skipping it), lay in the fact whether they are somehow bound to the class instance or not. For example, say whether the method receives a reference to the class instance during runtime
The
__dict__
dictionary property of the class object holds the reference to all the properties and methods of a class object and thusthe method foo is accessible as above. An important point to note here is that everything in python is an object and so references in the dictionary above are themselves pointing to other objects. Let me call them Class Property Objects - or as CPO within the scope of my answer for brevity.
If a CPO is a descriptor, then python interpretor calls the
__get__()
method of the CPO to access the value it contains.In order to determine if a CPO is a descriptor, python interpretor checks if it implements the descriptor protocol. To implement descriptor protocol is to implement 3 methods
for e.g.
where
self
is the CPO (it could be an instance of list, str, function etc) and is supplied by the runtimeinstance
is the instance of the class where this CPO is defined (the object 'c' above) and needs to be explicity supplied by usowner
is the class where this CPO is defined(the class object 'C' above) and needs to be supplied by us. However this is because we are calling it on the CPO. when we call it on the instance, we dont need to supply this since the runtime can supply the instance or its class(polymorphism)value
is the intended value for the CPO and needs to be supplied by usNot all CPO are descriptors. For example
This is because the list class doesnt implement the descriptor protocol.
Thus the argument self in
c.foo(self)
is required because its method signature is actually thisC.__dict__['foo'].__get__(c, C)
(as explained above, C is not needed as it can be found out or polymorphed) And this is also why you get a TypeError if you dont pass that required instance argument.If you notice the method is still referenced via the class Object C and the binding with the class instance is achieved via passing a context in the form of the instance object into this function.
This is pretty awesome since if you chose to keep no context or no binding to the instance, all that was needed was to write a class to wrap the descriptor CPO and override its
__get__()
method to require no context. This new class is what we call a decorator and is applied via the keyword@staticmethod
The absence of context in the new wrapped CPO
foo
doesnt throw an error and can be verified as follows:Use case of a static method is more of a namespacing and code maintainability one(taking it out of a class and making it available throughout the module etc).
It maybe better to write static methods rather than instance methods whenever possible, unless ofcourse you need to contexualise the methods(like access instance variables, class variables etc). One reason is to ease garbage collection by not keeping unwanted reference to objects.
Methods in Python are a very, very simple thing once you understood the basics of the descriptor system. Imagine the following class:
Now let's have a look at that class in the shell:
As you can see if you access the
foo
attribute on the class you get back an unbound method, however inside the class storage (the dict) there is a function. Why's that? The reason for this is that the class of your class implements a__getattribute__
that resolves descriptors. Sounds complex, but is not.C.foo
is roughly equivalent to this code in that special case:That's because functions have a
__get__
method which makes them descriptors. If you have an instance of a class it's nearly the same, just thatNone
is the class instance:Now why does Python do that? Because the method object binds the first parameter of a function to the instance of the class. That's where self comes from. Now sometimes you don't want your class to make a function a method, that's where
staticmethod
comes into play:The
staticmethod
decorator wraps your class and implements a dummy__get__
that returns the wrapped function as function and not as a method:Hope that explains it.
Please read this docs from the Guido First Class everything Clearly explained how Unbound, Bound methods are born.
method_two won't work because you're defining a member function but not telling it what the function is a member of. If you execute the last line you'll get:
If you're defining member functions for a class the first argument must always be 'self'.