Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create staticmethod from an existing method outside of the class? ("unbound method" error)

Tags:

python

How can you make a class method static after the class is defined? In other words, why does the third case fail?


>>> class b:
...  @staticmethod
...  def foo():
...   pass
...
>>> b.foo()
>>> class c:
...  def foo():
...   pass
...  foo = staticmethod( foo )
...
>>> c.foo()
>>> class d:
...  def foo():
...   pass
...
>>> d.foo = staticmethod( d.foo )
>>> d.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead)
like image 655
William Pursell Avatar asked Jan 19 '12 01:01

William Pursell


People also ask

What is unbound method?

An unbound method is essentially a function with some trimmings. A 'bound method' is called that because the first argument (ie self ) is already set to a ; you can call b(10) and it works just the same way as if you had done a. fred(10) (this is actually necessary given how CPython operates).

Can static methods be bound to an instance of a class?

Static methods can be bound to either a class or an instance of a class. Static methods serve mostly as utility methods or helper methods, since they can't access or modify a class's state. Static methods can access and modify the state of a class or an instance of a class.

Do static methods take self?

A static method is precisely one which does not take self because it does not need to call other instance methods, or would do so via the class name.

Can a static method be called from non static method Python?

Static method called with data So Cool! So the answer is yes, you can cal non-static methods from static methods. But only if you can pass in an instance as first parameter. So you either have to generate it from inside the static method (and in that case you are probably better off with a class method) or pass it in.


2 Answers

After the class is defined, foo is an unbound method object (a wrapper that ties the function to the class), not a function. The wrapper's going to try to pass an instance of the class (self) to the function as the first argument and so it complains that you haven't given it one.

staticmethod() should really be used only with functions. While the class is still being defined (as in your b and c) foo() is still a function, as the method wrapper is applied when the class definition is complete.

It's possible to extract the function from the unbound method object, apply staticmethod(), and assign it back to the class.

class d(object):
    def foo():
       pass

d.foo = staticmethod(d.foo.im_func)

In Python 3, there are no unbound instance methods (methods stored on classes are plain functions). So your original code would actually work fine on Python 3.

A way that works on both Python 2 and Python 3 is:

d.foo = staticmethod(d.__dict__['foo'])

(It also avoids creating and discarding the method wrapper.)

like image 103
kindall Avatar answered Sep 30 '22 13:09

kindall


You must pass the function, not the unbound method.

>>> class d:
...   def foo():
...     pass
... 
>>> d.foo = staticmethod(d.foo.im_func)
>>> d.foo()
like image 44
Ignacio Vazquez-Abrams Avatar answered Sep 30 '22 11:09

Ignacio Vazquez-Abrams