如何根据枚举类型重载python类方法
Posted
技术标签:
【中文标题】如何根据枚举类型重载python类方法【英文标题】:How do you overload python class method based on Enum type 【发布时间】:2021-12-25 06:08:03 【问题描述】:我正在尝试为使用重载类型装饰器的类创建一个 python 方法。我希望根据传递的 Enum 类型重载该方法。例如,
class GetPortType(enum.Enum):
DIFF_1: "Diff1"
DIFF_2: "Diff2"
SAME_1: "Same1"
SAME_2: "Same2"
class Port:
...
@typing.overload
def get_port_on_type(self, type: GetPortType.DIFF_1, num: int, skip: Optional[List]):
statement1
statement2
return [values]
@typing.overload
def get_port_on_type(self, type: GetPortType.DIFF_2, num: int, skip: Optional[List]):
statement3
statement4
return [values]
@typing.overload
def get_port_on_type(self, type: GetPortType.SAME_1, num: int, skip: Optional[List]):
statement1
statement3
return [values]
@typing.overload
def get_port_on_type(self, type: GetPortType.SAME_2, num: int, skip: Optional[List]):
statement2
statement4
return [values]
我如何实现这一目标?我应该为所有这些情况的枚举和返回类型创建一个“def __ new __(self, value):”方法吗?
编辑:我想知道我们是否可以对 Metaclass 做一些事情,比如返回值类型?哪个可能是这个元类的属性?
@property
def type(self):
return type(self.value)
""" changing the type annotation """
type: GetPortType.SAME_2.type
【问题讨论】:
你试过typing.Literal
。例如,最后一个的类型是Literal[GetPortType.SAME_2]
。
我想你不明白,typing.overload
不会让你实际使用方法重载。它仅用于类型注释。
type: GetPortType.DIFF_2
那不是类型!
@FrankYellin 仔细观察,OP 似乎认为您可以根据重载签名拥有 不同的实现。
@juanpa.arrivillaga 哎呀。我以为他们只是在问一个打字问题。对不起。
【参考方案1】:
您似乎误解了typing.overload
的作用。它不让您定义在不同情况下运行的不同版本的代码。相反,它用于类型提示,表示单个实现支持多种类型组合。函数的任何重载定义都不会运行,它们仅为稍后出现的函数的真实版本添加更好的类型提示。
这是一个例子given in the documentation:
@overload
def process(response: None) -> None:
...
@overload
def process(response: int) -> tuple[int, str]:
...
@overload
def process(response: bytes) -> str:
...
def process(response):
<actual implementation>
请注意,...
省略号文字是您可能实际放入此代码的内容,它并不代表仅用于文档的内容。在那些 @overload
装饰的函数中不需要主体,因为它们从不运行。 ...
文字似乎已经出现在类型提示爱好者中,作为函数存根的首选主体,而不是 pass
(至少曾经是函数的首选“什么都不做”主体)。
如果您确实需要一个能够根据参数类型运行不同版本的函数的装饰器,您可以使用functools.singledispatch
。但它仅分派实际类型,而不是您想要的文字值(例如 Enum
的特定实例)。
解决问题的简单方法是编写一组 if
/elif
/else
块,以便在您进入函数后将调用分开:
def get_port_on_type(self, type: GetPortType, num: int, skip: Optional[List]):
if type == GetPortType.DIFF_1:
do_stuff_1()
elif type == GetPortType.DIFF_2:
do_stuff_2()
elif type == GetPortType.SAME_1:
do_stuff_3()
else: # type == GetPortType.SAME_2:
do_stuff_4()
从 Python 3.10 开始,您可以使用新的 match
and case
statements 来做与上面的 if
/elif
/else
代码链基本相同的事情,语法稍微好一点,但我我仍在使用 3.9,我没有信心为您编写一个我无法测试的示例(有关新语句类型的教程,请参阅 PEP 636)。
【讨论】:
以上是关于如何根据枚举类型重载python类方法的主要内容,如果未能解决你的问题,请参考以下文章