【发布时间】:2021-03-03 20:32:45
【问题描述】:
我编写了一个小实用程序来解码由位标志组成的日志输出。我在解码这些位标志时使用枚举。
python --version
Python 3.8.6
为简洁起见,我只想打印枚举成员名称。我已将我的问题提炼为这个简短的 sn-p:
from enum import IntFlag
class Foo(IntFlag):
A = 0x01
B = 0x02
C = 0x04
def __str__(self):
return self.name
__repr__ = __str__
如果我将它们单独显示或将它们作为列表的一部分打印,则效果很好。但我无法打印 or 表达式。我想在A|B|C 表单上显示标志。
>>> Foo.A
A
>>> Foo.B
B
>>> [Foo.A, Foo.B]
[A, C]
>>> Foo.A | Foo.B
TypeError: __repr__ returned non-string (type NoneType)
更新:我查看了错误的源代码版本。 3.8.6 标签的IntFlag::__repr__ 确实包含打印每个成员https://github.com/python/cpython/blob/v3.8.6/Lib/enum.py#L761 的代码
我尝试阅读 CPythons Lib/enum.py,但无法弄清楚默认 IntFlag(没有我覆盖的 __repr__)如何在 Foo.A|Foo.B 表单上打印输出。~~
我可以看到IntFlag.__or__ 通过调用__class__ 返回了一个新对象(我真的不知道__class__ 做了什么)。而Enum.__repr__ 只打印一个类名和枚举名。
如何编写一个 __repr__ 函数和一个返回当前设置的枚举成员名称的字符串表示形式的 __str__ 函数?
【问题讨论】:
-
您正在阅读错误版本的源代码 - 您正在寻找的
__repr__行为最近在 master 分支中被删除。 (始终查看您实际使用的版本的代码!) -
enum有太多奇怪的魔法。 -
@user2357112supportsMonica 啊,你是对的:github.com/python/cpython/blob/v3.8.6/Lib/enum.py#L761 有一个循环打印枚举成员。我同意你的观点,enum.py 内部发生了很多事情。