2011-09-10 7 views
6

uno puede hacer algo como esto:Usando misma función que en la instancia y classmethod pitón

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 se define en "Creating a method that is simultaneously an instance and class method".

Mi pregunta es, ¿por qué es así, que el primer parámetro predeterminado no se puede usar como parámetro de comboclass. O al menos, ¿por qué no puedo pasar object to classmethod como primer parámetro? Sé cuál es la diferencia entre classmethod y instancemethods y lo que son decoradores, pero podría no entender cómo se hace el paso de parámetro incorporado @classmethod y self. ¿Hay solo algunas limitaciones técnicas? ¿O por qué no está integrado el combomethod?

+2

No utilice por favor el texto-habla ("algo bajo"), en los mensajes. –

+0

No puedo entender lo que está preguntando aquí ... –

+0

@Ignacio Quiero saber si estoy haciendo todo mal y ¿hay alguna manera más simple? Pensé que podría haber alguna forma incorporada para hacer lo mismo y si no, ¿por qué no? – Johu

Respuesta

3

combomethod no crea un objeto de método cuando se accede, sino una función envuelta especialmente. Al igual que los métodos, cada acceso crea un nuevo objeto, en este caso un nuevo objeto de función.

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. 

Es nuevo para cada acceso:

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

foo es realmente _wrapper disfrazada:

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

cuando se llama desde una clase del cierre tiene obj == Ninguno (tenga en cuenta que " self 'aquí se refiere al combomethod, que tiene una referencia al objeto de función original en 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>) 

Cuando llama como el atributo de una instancia, obj es la instancia:

>>> 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>) 

Aquí es la función original almacenado en el combomethod:

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

_wrapper ejecuta self.method, ya sea con la clase o instancia como el primer argumento dado el valor de obj:

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

Así que me dijiste cómo funcionaba el método y yo entendí la mayor parte. ¡Gracias por su esfuerzo! ¿Podría decirme también, por qué es malo y puede hacerse de una mejor manera? ¿La función Wrapper Around hace que la memoria sea ineficiente? – Johu

9

uso esto:

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() 
Cuestiones relacionadas