2011-09-10 9 views
6

si può fare qualcosa di simile:Utilizzando stessa funzione di istanza e classmethod in pitone

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 è definito in "Creating a method that is simultaneously an instance and class method".

La mia domanda è, perché è così, quel primo parametro di default non può essere usato come parametro di comboclass. O almeno, perché non posso passare l'oggetto a classmethod come primo parametro. So qual è la differenza tra classmethod e instancemethods e cosa sono i decoratori, ma potrei non capire, come viene effettuato il passaggio dei parametri @classmethod e self integrato. Ci sono solo alcune limitazioni tecniche? O perché non è già integrato lo combomethod?

+2

prega di non utilizzare il testo-parlare ("smth") nella post. –

+0

Non riesco a capire né la testa di quello che stai chiedendo qui ... –

+0

@Ignacio Voglio sapere se sto sbagliando tutto e c'è un modo più semplice? Ho pensato che potrebbe esserci un modo per fare la stessa cosa e se no, perché no? – Johu

risposta

3

combomethod non crea un oggetto metodo durante l'accesso ma una funzione appositamente spostata. Come i metodi, ogni accesso crea un nuovo oggetto, in questo caso un nuovo oggetto funzione.

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. 

E 'nuovo per ogni accesso:

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

foo è davvero _wrapper sotto mentite spoglie:

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

quando chiamato da una classe della chiusura ha obj == None (nota che' auto 'qui si riferisce al combometode, che ha un riferimento all'oggetto funzione originale 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>) 

Quando chiamato come attributo di un'istanza, obj è l'istanza:

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

Ecco la funzione originale memorizzata nella combomethod:

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

_wrapper esegue self.method sia con la classe o istanza come primo argomento dato il valore di obj:

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

Quindi mi hai detto come combometode ha funzionato e ho capito la maggior parte di esso. Grazie per l'impegno! Potresti anche dirmi, perché è cattivo e può essere fatto in un modo migliore? La funzione wrapper around rende la memoria inefficiente? – Johu

9

uso questo:

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() 
Problemi correlati