我正在为python编写自己的Enum
类,但我无法让__str__
和__repr__
正常工作,我做错了什么?
In [2]: x = Enum(X=1, Y=2)
In [3]: x
Out[3]: common.utils.Enum
In [4]: str(x)
Out[4]: "<class 'common.utils.Enum'>"
In [5]: x.__repr__
Out[5]: <bound method type.reprfun of <class 'common.utils.Enum'>>
In [6]: x.__repr__()
Out[6]: 'Enum(Y=2, X=1)'
代码本身:
def Enum(*args, **kwargs):
enums = dict(zip(args, range(len(args))), **kwargs)
def reprfun(self):
res = 'Enum(' +\
', '.join(map(lambda x: '{}={}'.format(x[0],x[1]), enums.items())) +\
')'
return res
reverse = dict((value, name) for name, value in enums.items())
typedict = enums.copy()
typedict['name'] = reverse
instance = type('Enum', (), typedict)
instance.__repr__ = types.MethodType(reprfun, instance)
instance.__str__ = types.MethodType(reprfun, instance)
return instance
答案 0 :(得分:7)
必须在类中添加特殊方法,而不是实例。总是在类型上查找任何特殊方法。
如果Python不能像那样工作,你就不能使用repr(ClassObj)
,因为它会调用ClassObj.__repr__
方法,它会将self
作为第一个参数。所以Python改为调用type(obj).__repr__(obj)
。
对于新式类,只保证在对象的类型上定义特殊方法的隐式调用才能正常工作,而不是在对象的实例字典中。
[...]
此行为背后的基本原理在于许多特殊方法,例如哈希()和 repr (),这些方法由所有对象(包括类型对象)实现。如果这些方法的隐式查找使用了传统的查找过程,那么在类型对象本身上调用它们时会失败:
>>> >>> 1 .__hash__() == hash(1) True >>> int.__hash__() == hash(int) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor '__hash__' of 'int' object needs an argument
以下作品:
typedict = enums.copy()
typedict.update({
'name': reverse,
'__repr__': reprfun,
'__str__': reprfun,
})
instance = type('Enum', (), typedict)
return instance
你确实要小心命名; instance
绑定到类对象,而不是实例。这个名字因此具有误导性。您可能希望使用cls
或classobj
或类似代替instance
。
演示:
>>> x = Enum(X=1, Y=2)
>>> x
<class '__main__.Enum'>
>>> x.__repr__
<unbound method Enum.reprfun>
>>> x()
Enum(Y=2, X=1)
>>> str(x())
'Enum(Y=2, X=1)'
>>> repr(x())
'Enum(Y=2, X=1)'