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()
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
>>> 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
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:
>>> C.foo <unbound method C.foo> >>> 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.
C.foo is roughly equivalent to this code in that special case:
>>> C.__dict__['foo'].__get__(None, C) <unbound method C.foo>
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 C.foo 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
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.