python - 带有强制关键字参数的自定义类的 Python 枚举
问题描述
我正在尝试使用具有强制性位置参数的自定义类创建一个枚举。
class Coord:
def __init__(self, *, x, y):
self._x = x
self._y = y
我想用这个类做几个枚举。像:
class IntCoord(Coord, Enum):
ONE_ONE = Coord(x=1, y=1)
class FloatCoord(Coord, Enum):
ONE_ONE = Coord(x=0.1, y=0.1)
这样我就可以在其他类中使用它们,例如:
class System(Generic[T]):
@classmethod
def get_one_one(cls) -> T:
return NotImplemented
class IntSystem(System[IntCoord]):
@classmethod
def get_one_one(cls) -> IntCoord:
return IntCoord.ONE_ONE
class FloatSystem(System[FloatCoord]):
@classmethod
def get_one_one(cls) -> FloatCoord:
return FloatCoord.ONE_ONE
之后,我想比较枚举:
IntCoord(x=1, y=1) is IntSystem.get_one_one()
我很难定义Coord
班级。似乎不可能通过以下方式实例化Coord
枚举类Coord(x=1, y=1)
有没有用枚举实现这一目标的好方法?还是更好的合理实施?
完整脚本如下:
from enum import Enum
from typing import Generic, TypeVar
class Coord:
def __init__(self, *, x, y):
self._x = x
self._y = y
class IntCoord(Coord, Enum):
ONE_ONE = Coord(x=1, y=1)
class FloatCoord(Coord, Enum):
ONE_ONE = Coord(x=0.1, y=0.1)
T = TypeVar('T', bound=Coord)
class System(Generic[T]):
@classmethod
def get_one_one(cls) -> T:
return NotImplemented
class IntSystem(System[IntCoord]):
@classmethod
def get_one_one(cls) -> IntCoord:
return IntCoord.ONE_ONE
class FloatSystem(System[FloatCoord]):
@classmethod
def get_one_one(cls) -> FloatCoord:
return FloatCoord.ONE_ONE
if __name__ == '__main__':
int_one_one = IntSystem.get_one_one()
float_one_one = FloatSystem.get_one_one()
print(IntCoord(x=1, y=1) is int_one_one)
print(FloatCoord(x=0.1, y=0.1) is float_one_one)
错误是:
Traceback (most recent call last):
File "test.py", line 11, in <module>
class IntCoord(Coord, Enum):
File ".pyenv/versions/3.9.0/lib/python3.9/enum.py", line 228, in __new__
enum_member.__init__(*args)
TypeError: __init__() takes 1 positional argument but 2 were given
解决方案
你遇到的问题Coord
是Enum
你说你的 enum 也是 a Coord
,并且 aCoord
需要两个参数——但你只给你的 enum 成员ONE_ONE
一个参数...... a Coord
。
有两种方法可以解决这个问题:
- 不要
Coord
在您的枚举成员中使用 a (并丢失您的关键字(不是位置)参数):
class Coord:
def __init__(self, x, y):
self._x = x
self._y = y
class IntCoord(Coord, Enum):
ONE_ONE = 1, 1
- 不要
Coord
在您的枚举标头中使用(并保留您的关键字参数,但添加sproperty
以便仍然有效]:blah._x
blah._y
class Coord:
def __init__(self, *, x, y):
self._x = x
self._y = y
class IntCoord(Enum):
#
ONE_ONE = Coord(x=1, y=1)
#
@property
def _x(self):
return self.value._x
#
@property
def _y(self):
return self.value._y
如果您改用aenum
1库,它确实会变得更容易:
from aenum import Enum, enum
class Coord:
def __init__(self, *, x, y):
self._x = x
self._y = y
class IntCoord(Coord, Enum):
#
ONE_ONE = enum(x=1, y=1)
并在使用中:
>>> IntCoord.ONE_ONE
<IntCoord.ONE_ONE: enum(x=1, y=1)>
>>> IntCoord.ONE_ONE._y
1
请注意,在上述所有情况下,IntCoord.ONE_ONE
按值检索比平时要复杂一些:
IntCoord((1, 1))
IntCoord(Coord(x=1, y=1))
IntCoord(enum(x=1, y=1))
--
1披露:我是Python stdlibEnum
、enum34
backport和Advanced Enumeration ( aenum
) 库的作者。
推荐阅读
- python - 选择项目并通过鼠标单击从 QlistWidget 更新 QLineedit?
- vb.net - 当文本转换为大写时,Windows Search 无法找到文件
- python - 网页抓取拦截器
标签
- c# - WPF WebView2 - 无法禁用上下文菜单
- c# - C#如何将字符串变量视为插值字符串?
- node.js - 如何从 API 显示数组的对象?
- flutter - 在 Flutter Dart 的另一个枚举映射中使用枚举映射属性值
- ios - 如何使用自定义编程 UIView [Swift 5] 更改 UILabel 的属性
- python - Selenium 登录网站后没有显示结果
- java - 如何从 JAVA 中的 UTF-8 代码中取回主角?