2012-08-29 15 views
9

Cari Python 3 esperti,python2 vs funzione python3 al metodo di rilegatura

con python2, si potrebbe procedere come segue (so che questo è un po 'peloso, ma non è questo il punto qui: p):

class A(object): 
    def method(self, other): 
    print self, other 

class B(object): pass 

B.method = types.MethodType(A().method, None, B) 
B.method() # print both A and B instances 

con python3, non ci sono più metodi non associati, solo funzioni. Se voglio lo stesso comportamento, suona come ho di introdurre un descrittore personalizzato come ad esempio:

class UnboundMethod: 
    """unbound method wrapper necessary for python3 where we can't turn 
    arbitrary object into a method (no more unbound method and only function 
    are turned automatically to method when accessed through an instance) 
    """ 
    def __init__(self, callable): 
     self.callable = callable 

    def __get__(self, instance, objtype): 
     if instance is None: 
      return self.callable 
     return types.MethodType(self.callable, instance) 

così posso fare:

B.method = UnboundMethodType(A().method) 
B.method() # print both A and B instances 

C'è un altro modo per farlo senza scrivere tale descrittore?

TIA

+0

Commento rapido e off-topic: non è necessario derivare dall'oggetto in Py3. È sempre fatto implicitamente. Per controllare, basta 'stampare (anyobject .__ mro __)' (= Ordine di risoluzione dei metodi) – cfi

+0

Credo che questa sia una duplicazione di [http://stackoverflow.com/questions/10729909/convert-builtin-function-type-to-method -tipo-in-python-3]. Tuttavia questa domanda è probabilmente più facile da trovare. Inoltre è più chiaro (almeno per me), quindi voterei per mantenere questo ... – cfi

+0

@cfi, true sull'ereditarietà degli oggetti, codice UnboundMethod corretto. Inoltre hai ragione che è una domanda simile a quella di unire una funzione compilata/incorporata (che non ha una risposta soddisfacente btw) – sthenault

risposta

1
B.method = lambda o: A.method(o,A()) 

b = B() 
b.method() 

la linea b.method() poi chiama A.method(b,A()). Ciò significa che una A viene inizializzata ogni volta. Per evitare questo:

a = A() 
B.method = lambda o: A.method(o,a) 

ora ogni volta che si chiama b.method() su qualsiasi istanza di B la stessa istanza di A è passato come secondo argomento.

0

Bene, il tuo codice non funziona in Python 2, ma ottengo quello che stai cercando di fare. E puoi usare lambda, come nella risposta di Sheena, o functools.partial.

>>> import types 
>>> from functools import partial 

>>> class A(object): 
... def method(self, other): 
...  print self, other 
... 
>>> class B(object): pass 
... 
>>> B.method = partial(A().method, A()) 
>>> B().method() 
<__main__.A object at 0x112f590> <__main__.A object at 0x1132190> 
Problemi correlati