2012-08-29 17 views
9

Estimados pitón 3 expertos método,python2 vs función python3 a la unión

con python2, se podría hacer lo siguiente (ya sé que es un poco difícil, pero ese no es el punto aquí: 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, no hay más métodos independientes, solo funciones. Si quiero el mismo comportamiento, parece que tengo que introducir un descriptor de costumbre, tales como:

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) 

por lo que puedo hacer:

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

¿Hay alguna otra manera de hacerlo sin escribir tal descriptor?

TIA

+0

Comentario rápido, fuera del tema: No es necesario derivar del objeto en Py3. Siempre se hace implícitamente. Para verificar, simplemente 'print (anyobject .__ mro __) '(= orden de resolución de método) – cfi

+0

Creo que esta es una duplicación de [http://stackoverflow.com/questions/10729909/convert-builtin-function-type-to-method -type-in-python-3]. Sin embargo, esta pregunta es probablemente más fácil de encontrar. También está más claro (al menos para mí), así que votaría para mantener este ... – cfi

+0

@cfi, cierto sobre la herencia de objetos, muestra del código UnboundMethod fijo. También tienes razón en que es una pregunta similar a la de encuadernar una función compilada/incorporada (que no tiene una respuesta satisfactoria por cierto) – sthenault

Respuesta

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

b = B() 
b.method() 

la línea b.method() llama entonces A.method(b,A()). Esto significa que una A se inicializa cada vez. Para evitar esto:

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

ahora cada vez que llame b.method() en cualquier instancia de B la misma instancia de A se pasa como segundo argumento.

0

Bueno, tu código tampoco funciona en Python 2, pero entiendo lo que intentas hacer. Y puede usar lambda, como en la respuesta de 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>