Al usar metaclases, intento crear un método de instancia simplificando un método de instancia existente. El problema es que parcial no funciona con el método de instancia. Este es un ejemplo sencillo de lo que trato de lograr:Crear método de instancia en metaclase usando parcial en Python 3
from functools import partial
class Aclass(object):
def __init__(self, value):
self._value = value
def complex(self, a, b):
return a + b + self._value
class Atype(type):
def __new__(cls, name, bases, attrs):
return super(Atype, cls).__new__(cls, name, (Aclass,) + bases, attrs)
def __init__(cls, name, bases, attrs):
setattr(cls, 'simple', partial(cls.complex, b=1))
class B(metaclass=Atype):
pass
b = B(10)
print(b.complex(1, 2))
print(b.simple(1))
y la salida es:
13
Traceback (most recent call last):
File "metatest.py", line 22, in <module>
print(b.simple(1))
TypeError: complex() takes exactly 3 non-keyword positional arguments (1 given)
He resuelto utilizando lambda cambiante:
setattr(cls, 'simple', partial(cls.complex, b=1))
a:
setattr(cls, 'simple', lambda self, x: cls.complex(self, x, b=1))
pero es feo d tiene problemas con los parámetros opcionales.
Podría crear estos métodos en la instancia __init__
pero supongo que tiene más sentido, y es más eficiente hacerlo en la clase __init__
usando metaclases.
¿Alguna idea de cómo hacerlo correctamente?
@martineau: estoy a favor de usar la etiqueta python-3.x, pero no veo ninguna razón para no usar "python" junto a ella. Además, ¿no sería "python3" una etiqueta más limpia? – jsbueno
@jsbueno: de acuerdo, pero no me permitirá cambiar python-3.x a python3. – martineau
@jsbueno: La etiqueta es python-3.x, no sé cómo (si es que lo hace) estas cosas se deciden. Sospecho que podría discutirse en meta, y luego cambiar si hay apoyo para ello. En cualquier caso, python3 es un sinónimo, por lo que puede escribirlo, se reasignará. –