Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we **unsplat 'self' into a method? [duplicate]

>>> class Potato(object):
...     def method(self, spam):
...         print self, spam
... 
>>> spud = Potato()

Works:

>>> Potato.method(spud, **{'spam': 123})
<__main__.Potato object at 0x7f86cd4ee9d0> 123

Doesn't work:

>>> Potato.method(**{'self': spud, 'spam': 123})
# TypeError

But why not? I thought 'self' was just a convention, and there was nothing intrinsically special about this argument?

like image 847
wim Avatar asked Jun 11 '14 17:06

wim


1 Answers

Python 2's instancemethod wrapper object insists on inspecting the first positional argument, and that check does not support keyword arguments, full stop:

>>> Potato.method(self=spud, spam=123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method method() must be called with Potato instance as first argument (got nothing instead)

Note that I did not use argument unpacking there!

You can use positional arguments just fine:

>>> Potato.method(*(spud,), **{'spam': 123})
<__main__.Potato object at 0x1002b57d0> 123

or you can access the original function object:

>>> Potato.method.__func__(**{'self': spud, 'spam': 123})
<__main__.Potato object at 0x1002b57d0> 123

to bypass this limitation.

Python 3 no longer uses a method wrapper for unbound methods; the underlying function is returned directly instead.

like image 120
Martijn Pieters Avatar answered Nov 15 '22 19:11

Martijn Pieters