Using the same function as instance and classmethod in python

You can do something like this:

class master: @combomethod def foo(param): param.bar() # Param could be type as well as object class slaveClass( master ): @classmethod def bar(cls): print("This is class method") slaveType = slaveClass slaveType.foo() class slaveInstance( master ): def __init__(self, data): self.data = data def bar(self): print("This is "+self.data+" method") slaveType = slaveInstance("instance") slaveType.foo() 

combomethod defined in Creating a Method, which is both an instance and a class method .

My question is: why is it that the first default parameter cannot be used as a comboclass parameter. Or at least why I cannot pass a classmethod object as the first parameter. I know what the difference is between classmethod and instancemethods methods and what are decorators, but I may not understand how the @classmethod and self parameters are @classmethod . Are there only some technical limitations? Or why are there no combomethod already built-in?

+6
source share
2 answers

combomethod does not create a method object upon access, but a specially wrapped function. Like methods, each access creates a new object, in this case a new function object.

 class A: def __init__(self): self.data = 'instance' @combomethod def foo(param): if isinstance(param, A): print("This is an " + param.data + " method.") elif param is A: print("This is a class method.") >>> a = A() >>> A.foo <function foo at 0x00CFE810> >>> a.foo <function foo at 0x00CFE858> >>> A.foo() This is a class method. >>> a.foo() This is an instance method. 

This is new for every access:

 >>> A.foo is A.foo False >>> a.foo is a.foo False 

foo really _wrapper hiding:

 >>> A.foo.__code__.co_name '_wrapper' 

When called from a class, the closure has obj == None (note that here "self" refers to a combo method that has a link to the original function object in self.method ):

 >>> print(*zip(A.foo.__code__.co_freevars, A.foo.__closure__), sep='\n') ('obj', <cell at 0x011983F0: NoneType object at 0x1E1DF8F4>) ('self', <cell at 0x01198530: combomethod object at 0x00D29630>) ('objtype', <cell at 0x00D29D10: type object at 0x01196858>) 

When called as an instance attribute, obj is an instance:

 >>> print(*zip(a.foo.__code__.co_freevars, a.foo.__closure__), sep='\n') ('obj', <cell at 0x01198570: A object at 0x00D29FD0>) ('self', <cell at 0x01198530: combomethod object at 0x00D29630>) ('objtype', <cell at 0x00D29D10: type object at 0x01196858>) 

Here is the original function stored in the combo:

 >>> A.foo.__closure__[1].cell_contents.method <function foo at 0x00D1CB70> >>> A.foo.__closure__[1].cell_contents.method.__code__.co_name 'foo' 

_wrapper executes self.method with either the class or the instance as the first argument given by obj:

 if obj is not None: return self.method(obj, *args, **kwargs) else: return self.method(objtype, *args, **kwargs) 
+3
source

use this:

 class A(object): @classmethod def print(cls): print 'A' def __print(self): print 'B' def __init__(self): self.print = self.__print a = A() a.print() A.print() 
+9
source

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


All Articles