Me pregunto si es posible hacer un método que se comporta de manera diferente cuando se llama como un método de clase que cuando se llama como un método de instancia.¿Un método de clase que se comporta de manera diferente cuando se llama como un método de instancia?
Por ejemplo, como proyecto de mejora de habilidades, estoy escribiendo una clase Matrix
(sí, sé que ya hay clases de matriz perfectamente buenas). Creé un método de clase llamado identity
que devuelve una matriz de identidad de un tamaño específico.
Ahora, cuando se invoca en una instancia de Matrix
, parece lógico que no se deba especificar el tamaño; debe devolver una matriz de identidad del mismo tamaño que el Matrix
en el que se invoca.
En otras palabras, me gustaría definir un método que pueda determinar si se llamó a través de una instancia y, de ser así, acceder a los atributos de esa instancia. Desafortunadamente, incluso después de buscar en la documentación y en algunas búsquedas de Google, no encontré nada que sugiera que esto sea posible. ¿Alguien sabe de manera diferente?
Editar:
Wow! Claramente, todavía no estoy acostumbrado a las funciones de primera clase. Esto es lo que terminé con: ¡gracias a Desconocido por proporcionar la clave!
class Foo(object):
def __init__(self, bar):
self.baz = bar
self.bar = MethodType(lambda self: self.__class__.bar(self.baz), self, self.__class__)
@classmethod
def bar(cls, baz):
return 5 * baz
Foo.bar(3) # returns 15
foo = Foo(7)
foo.bar() # returns 35
Edición 2:
Sólo una pequeña nota - esta técnica (y la mayoría de los que se presentan a continuación) no funcionará en las clases que definen __slots__
, como no se puede reasignar el método.
La pregunta que se le hizo a un objeto único que se puede llamar que podría detectar cómo se llamó. (Esto debería ser posible utilizando el módulo de inspección para obtener el marco de llamada). La 'solución' presentada es crear un segundo método obligatorio, vinculado, que está vinculado a cada instancia con el mismo nombre que el primer llamante. Esto puede resolver el problema de cómo tener clases y 'métodos de instancia' con el mismo nombre. Pero no es lo mismo que tener un único invocable que pueda actuar como cualquiera de los dos. –
@TerryJanReedy ¿es posible inspeccionar el marco de llamada en tiempo de ejecución? – aayush
Sí, esto es lo que quise decir con "use el módulo de inspección para obtener el marco de llamada". Hay una o más funciones para esto. –