En Python, ¿puedes llamar a un método de instancia de clase A, pero pasar en una instancia de clase B?

En el interés de reutilizar un código existente que se definió como un método de instancia de una clase diferente, intenté hacer algo como lo siguiente:

class Foo(object): def __init__(self): self.name = "Foo" def hello(self): print "Hello, I am " + self.name + "." class Bar(object): def __init__(self): self.name = "Bar" bar = Bar() Foo.hello(bar) 

pero eso resulta en:

TypeError: el método no vinculado hello () debe llamarse con la instancia de Foo como primer argumento (en su lugar, tiene la instancia de Bar)

¿Es algo como esto posible?


Debería haber tenido claro que sé que es una mala idea. Obviamente la solución real es un poco de refactorización. Pensé que debía haber una manera, y resulta que sí.

Gracias por los comentarios.

Parece que esto funciona:

 Foo.hello.im_func(bar) 

Hola soy bar

Supongo que necesito leer un poco más este …

Ocurre porque la clase de envolturas de Python funciona como un “método independiente” que realiza esta comprobación de tipo. Hay una descripción de las decisiones involucradas en esto aquí .

Tenga en cuenta que esta comprobación de tipo se ha eliminado en Python 3 (consulte la nota al final de ese artículo), por lo que su enfoque funcionará allí.

Esta es una pregunta antigua, pero Python ha evolucionado y parece que vale la pena señalarlo:

con Python 3 no hay más , ya que un método es simplemente una !

Lo que probablemente significa que el código en la pregunta original no debe considerarse / that / off. Python siempre ha tratado de escribir pato en cualquier caso, ¿no es así?

Refs:

  • Guido propone eliminar métodos no enlazados de python
  • Novedades de la versión de Python 3
  • Obtenga la clase definitoria de objeto de método independiente en Python 3

Solución alternativa en Py2

Tenga en cuenta que también hay una solución alternativa a la pregunta “exploratoria” (vea Python: ¿Enlazar un método sin unir? ):

 In [6]: a = Aaim_func.__get__(B(), B) In [7]: a Out[7]: > In [8]: a(2) 2 

Árbitro:

Algunos ejemplos de código ipython

python 2

 In [1]: class A(): def a(self, a=0): print a ...: In [2]: Aa Out[2]:  In [3]: Aaim_func Out[3]:  In [4]: Aa(B()) --------------------------------------------------------------------------- TypeError Traceback (most recent call last)  in () ----> 1 Aa(B()) TypeError: unbound method a() must be called with A instance as first argument (got B instance instead) 

python 3

 In [2]: class A(): def a(self, a=0): print(a) ...: In [3]: def a(): ...: pass ...: In [4]: class B(): ...: pass In [5]: Aa(B()) 0 In [6]: Aa Out[6]:  

Hace un tiempo, me preguntaba sobre la misma “característica” en Perl en PerlMonks, y el consenso general fue que mientras funciona (como lo hace en Python) no debería estar haciendo las cosas de esa manera.