如何使用 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
以下代码按预期工作
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