Class method differences in Python: bound, unbound and static Class method differences in Python: bound, unbound and static python python

Class method differences in Python: bound, unbound and static

In Python, there is a distinction between bound and unbound methods.

Basically, a call to a member function (like method_one), a bound function


is translated to


i.e. a call to an unbound method. Because of that, a call to your version of method_two will fail with a TypeError

>>> a_test = Test() >>> a_test.method_two()Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: method_two() takes no arguments (1 given) 

You can change the behavior of a method using a decorator

class Test(object):    def method_one(self):        print "Called method_one"    @staticmethod    def method_two():        print "Called method two"

The decorator tells the built-in default metaclass type (the class of a class, cf. this question) to not create bound methods for method_two.

Now, you can invoke static method both on an instance or on the class directly:

>>> a_test = Test()>>> a_test.method_one()Called method_one>>> a_test.method_two()Called method_two>>> Test.method_two()Called method_two

Methods in Python are a very, very simple thing once you understood the basics of the descriptor system. Imagine the following class:

class C(object):    def foo(self):        pass

Now let's have a look at that class in the shell:

>>><unbound method>>>> C.__dict__['foo']<function foo at 0x17d05b0>

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. is roughly equivalent to this code in that special case:

>>> C.__dict__['foo'].__get__(None, C)<unbound method>

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 that None is the class instance:

>>> c = C()>>> C.__dict__['foo'].__get__(c, C)<bound method of <__main__.C object at 0x17bd4d0>>

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:

 class C(object):  @staticmethod  def foo():   pass

The staticmethod decorator wraps your class and implements a dummy __get__ that returns the wrapped function as function and not as a method:

>>> C.__dict__['foo'].__get__(None, C)<function foo at 0x17d0c30>

Hope that explains it.

When you call a class member, Python automatically uses a reference to the object as the first parameter. The variable self actually means nothing, it's just a coding convention. You could call it gargaloo if you wanted. That said, the call to method_two would raise a TypeError, because Python is automatically trying to pass a parameter (the reference to its parent object) to a method that was defined as having no parameters.

To actually make it work, you could append this to your class definition:

method_two = staticmethod(method_two)

or you could use the @staticmethod function decorator.