Assign a modular method to a class variable or instance variable

In a.py module

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 a module, I can easily assign a function to a variable. When inside the class, try assigning the module level function of the class variable func = task , it shows an error, to remove this error, I have to replace it with func = task .__ call __ But when I assign the instance variable my work self.func_1 = task .

My question is: why can't I assign a module level function to a class variable without __ calling __ and when does the same function work that I can assign to an instance variable.

+5
source share
1 answer

Since you displayed the function as an unrelated method A , so when you call cls.func , you first set something equal to getattr(cls, 'func') , which returns the <unbound method A.task> BUT, you need to call this unbound method with the class as the first argument.

Since cls.func in this particular case means β€œgives me the class attribute func of cls ”, it cannot mean β€œ func class method” at the same time - it means Python does not translate cls.func() to func(cls) .

But at the same time, since func is the <unbound method A.task> (bound to A.task ), it needs to be called as func(cls) to work.

Mark this as follows:

 @classmethod def test(cls): print getattr(cls, 'func') # <unbound method A.task> 

You can fix this 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 unrelated methods, this only works with python2.x

+1
source

Source: https://habr.com/ru/post/1270053/


All Articles