2012-08-29 12 views
9

Drodzy python 3 ekspertów,python2 vs funkcji python3 do sposobu wiązania

z python2, można wykonać następujące czynności (wiem, że to jest nieco owłosione, ale nie o to tu chodzi: 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 

z python3, nie ma więcej niezwiązanych metod, tylko funkcje. Jeśli chcę to samo zachowanie, to brzmi jak mam przedstawić własny deskryptor takich jak:

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) 

więc mogę zrobić:

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

Czy jest jakiś inny sposób to zrobić bez pisemnej taki deskryptor?

TIA

+0

Szybki, nietypowy komentarz: Nie trzeba wyprowadzać z obiektu w Py3. Zawsze odbywa się to w sposób dorozumiany. Aby to sprawdzić, po prostu 'print (anyobject .__ mro __)' (= metoda Rozdzielczość metody) – cfi

+0

Wierzę, że jest to duplikacja [http://stackoverflow.com/questions/10729909/convert-builtin-function-type-to-method -type-w-python-3]. Jednak to pytanie jest prawdopodobnie łatwiejsze do znalezienia. Również jest bardziej jasne (przynajmniej dla mnie), więc chciałbym głosować, aby zachować ten ... – cfi

+0

@ cfi, prawda o dziedziczeniu obiektów, naprawiono UnboundMethod code sample. Również masz rację, że jest to podobne pytanie, jak w przypadku wiązania skompilowanej/wbudowanej funkcji (która nie ma satysfakcjonującej odpowiedzi btw). – sthenault

Odpowiedz

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

b = B() 
b.method() 

linia b.method() następnie wywołuje A.method(b,A()). Oznacza to, że A jest inicjowane za każdym razem. Aby tego uniknąć:

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

teraz za każdym razem dzwonić b.method() na każdej instancji B ta sama instancja jest przekazywana jako drugi argument.

0

Cóż, twój kod również nie działa w Pythonie 2, ale dostaję to, co próbujesz zrobić. I możesz użyć lambda, jak w odpowiedzi Sheeny, lub 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> 
Powiązane problemy