Reputation: 19805
This is how we make static functions in Python:
class A:
@staticmethod
def fun():
print 'hello'
A.fun()
This works as expected and prints hello
.
If it is a member function instead of a static one, we use self
:
class A:
def fun(self):
print 'hello'
A().fun()
which also works as expected and prints hello
.
My confusion is with the following case:
class A:
def fun():
print 'hello'
In the above case, there is no staticmethod
, nor self
. Python interpreter is okay with this definition. However, we cannot call it either of the above methods, namely:
A.fun()
A().fun()
both gives errors.
My question is: Is there any way that I can call this function? If not, why Python do not give me a syntax error in the first place?
Upvotes: 3
Views: 62
Reputation: 1121306
Python doesn't give you a syntax error, because the binding of a method (which takes care of passing in self
) is a runtime action.
Only when you look up a method on a class or instance, is a method being bound (because functions are descriptors they produce a method when looked up this way). This is done via the descriptor.__get__()
method, which is called by the object.__getattribute__()
method, which Python called when you tried to access the fun
attribute on the A
class or A()
instance.
You can always 'unwrap' the bound method and reach for the un-wrapped function underneath to call it directly:
A.fun.__func__()
Incidentally, that's exactly what staticmethod
does; it is there to 'intercept' the descriptor binding and return the raw function object instead of a bound method. In other words, staticmethod
undoes the normal runtime method binding:
Demo:
>>> class A(object): pass
...
>>> def fun(): print 'hello!'
...
>>> fun.__get__(None, A) # binding to a class
<unbound method A.fun>
>>> fun.__get__(None, A)() # calling a bound function, fails as there is no first argument
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method fun() must be called with A instance as first argument (got nothing instead)
>>> fun.__get__(None, A).__func__ # access the wrapped function
<function fun at 0x100ba8378>
>>> staticmethod(fun).__get__(None, A) # staticmethod object just returns the function
<function fun at 0x100ba8378>
>>> staticmethod(fun).__get__(None, A)() # so calling it works
hello!
Upvotes: 9