如何使用 python 类型函数设置内置 class 方法?

How to set builtin class methods with python type function?

以下代码按预期工作

class Foo: pass
a1 = Foo
a2 = Foo
print(a1 == a2)
# True

现在如果我动态生成它们并进行比较它不起作用

def eq(a,b):
  return str(a) == str(b)

t1 = type("Foo", (), {"__eq__": eq})
t2 = type("Foo", (), {"__eq__": eq})

print(t1 == t2)
# False

而且当运行这个时候,我得到错误

print(t1.__eq__(t2))

Traceback (most recent call last):
  File "foo.py", line 51, in <module>
    print(t1.__eq__(t2))
TypeError: eq() missing 1 required positional argument: 'b'

使用类型函数设置内置方法的正确方法是什么?

旁注:
我需要这种功能,我从类型动态创建类型(在这种情况下它是一个身份函数,我 return 输出与输入相同)或类型注释不是类型类型但 typing.Alias 或 typing.Generic。这是获得更大图片的片段

from typing import List
class Foo: pass

def build_type(type_):
  '''Build type definition of new user-defined types or annotations.'''

  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
    type_name = str(type_)
    attrs = {
      "__origin__": origin,
      "__args__": args,
      "__hash__": hash((type_name, origin, args))
    }
    return type(type_name, (), attrs)

t1 = build_type(Foo)
t2 = build_type(Foo)
print(t1 == t2) # True

a1 = build_type(List[Foo])
a2 = build_type(List[Foo])

print(a1 == a2) # False

您的代码目前 returns:

id(a1)
140415204390672

id(a2)
140415204390672

# a1 and a2 have same object IDs

id(t1)
140415116432032

id(t2)
140415116465120

# t1 and t2 have different object ID

但我猜你想比较一下:

a1.__name__ == a2.__name__
True

其中 a1.__name__'Foo'

如评论中所述,方法必须是 class 的成员,而不是实例的成员。

由于您正在动态构建 classes 而不是简单的对象,因此您应该使用具有特定 __eq__ 方法的自定义元 class:

你的例子会变成:

...
class Builder(type):
"""Custom meta-class defining type equality as name equality"""
    def __eq__(self, other):
        return str(self) == str(other)

def build_type(type_):
  '''Build type definition of new user-defined types or annotations.'''

  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
    type_name = str(type_)
    attrs = {
      "__origin__": origin,
      "__args__": args,
      "__hash__": hash((type_name, origin, args))
    }
    return Builder(type_name, (), attrs)
...

如果你 运行 它,你应该得到预期的结果:

True
True