Cómo configurar métodos de clase incorporados con la función de tipo de Python?
El siguiente código funciona como se espera
class Foo: pass
a1 = Foo
a2 = Foo
print(a1 == a2)
<h1>True</h1>
<p><code>
ahora, si los genero dinámicamente y los comparo, no funciona
</code>
def eq(a,b):
return str(a) == str(b)</p>
<p>t1 = type("Foo", (), {"<strong>eq</strong>": eq})
t2 = type("Foo", (), {"<strong>eq</strong>": eq})</p>
<p>print(t1 == t2)</p>
<h1>False</h1>
<p>```</p>
Además, al ejecutar esto, obtengo el error
print(t1.eq(t2))
Traceback (most recent call last):
File “foo.py”, line 51, in
print(t1.eq(t2))
TypeError: eq() missing 1 required positional argument: ‘b’
¿Cuál es la forma correcta de configurar un método incorporado utilizando una función de tipo?
nota al margen:<br>
Necesito este tipo de funcionalidad, donde estoy creando dinámicamente los tipos ya sea a partir de tipos (en este caso es una función de identidad donde devuelvo la salida igual que la entrada) o anotaciones de tipo que no son del tipo tipo sino typing.Alias o typing.Generic. Aquí está el fragmento para tener una imagen más grande
from typing import List
class Foo: pass
def buildtype(type):
”’Construir la definición de tipo de nuevos tipos o anotaciones definidas por el usuario.”’
if isinstance(type, type):
return type
else:
origin = type.origin if hasattr(type, “origin“) else None
args = type.args if hasattr(type, “args“) else None
typename = str(type)
attrs = {
“origin“: origin,
“args“: args,
“hash“: hash((typename, origin, args))
}
return type(typename, (), attrs)
t1 = buildtype(Foo)
t2 = buildtype(Foo)
print(t1 == t2) # True
a1 = buildtype(List[Foo])
a2 = buildtype(List[Foo])
print(a1 == a2) # False
“`
davy.ai
El problema con las clases
t1
yt2
generadas dinámicamente es que tienen un métodoeq
personalizado que solo toma un argumentoa
. Sin embargo, cuando se comparat1 == t2
, Python automáticamente llama al método__eq__
incorporado que toma dos argumentosself
yother
. Por lo tanto, aparece el mensaje de error “falta 1 argumento posicional requerido: ‘b'”.Para solucionar este problema, debes definir el método
__eq__
personalizado en las clasest1
yt2
para que tomen dos argumentos en lugar de uno.Aquí está el código actualizado:
Esto ahora debería funcionar como se espera y devolver
True
.En cuanto a la función
build_type
, puedes modificarla para incluir también el método__eq__
en la definición de tipo generado, similar a la claseFoo
anterior. Esto se puede hacer de la siguiente manera:Esto ahora generará correctamente el método
__eq__
para todos los tipos generados dinámicamente, incluido el ejemploList[Foo]
.