In module a.py
def task():
print "task called"
a = task
class A:
func = task # this show error unbound method
#func = task.__call__ # if i replace with this work
def __init__(self):
self.func_1 = task
def test_1(self):
self.func_1()
@classmethod
def test(cls):
cls.func()
a()
A().test_1()
A.test()
Output:
task called
task called
Traceback (most recent call last):
File "a.py", line 26, in <module>
A.test()
File "a.py", line 21, in test
cls.func()
TypeError: unbound method task() must be called with A instance as
first argument (got nothing instead)
In the module, I can easily assign a function to a variable. When inside class try to assign module level function to class variable func = task it shows error, to remove this error I have to replace it with func = task.__call__ But when I assign to instance variable its work self.func_1 = task.
My Question is: why I can't assign a module level function to a class variable without __call__ and when the same function I can assign to an instance variable is working.
Because you mapped a function as unbound method of A
, so when you are calling cls.func
you first ask something equals to getattr(cls, 'func')
which returns <unbound method A.task>
BUT, this unbound method needs to be called with class as first argument.
So because in this specific case cls.func
means "gives me class attribute func
of cls
" it can not means to the same time "call class method func
" - So Python doesn't translate cls.func()
by func(cls)
.
But within the same time, because func
is <unbound method A.task>
(bound to A.task
) it needs to be called like func(cls)
to work.
Check it with something like:
@classmethod
def test(cls):
print getattr(cls, 'func') # <unbound method A.task>
You could fix it with something like:
def task(cls=None):
if cls is None:
print 'task()'
else:
print 'A.foo({})'.format(cls)
a = task
class A:
func = task # this show error unbound method
def __init__(self):
self.func_1 = task
def test_1(self):
self.func_1()
@classmethod
def test(cls):
cls.func(cls())
a()
A().test_1()
A.test()
Output:
task()
task()
A.foo(<__main__.A instance at 0x7fd0310a46c8>)
Note that python3 removes unbound methods, this works only with python2.x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With