如何根据 Enum 类型重载 python class 方法
How do you overload python class method based on Enum type
我正在尝试为 class 创建一个 python 方法,它使用重载类型装饰器。我希望根据传递的枚举类型重载该方法。例如,
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]
我该如何实现?我是否应该为所有这些情况创建枚举和 return 类型的“def __ new __(self, value):”方法?
编辑:我想知道我们是否可以使用 Metaclass 做一些事情,比如值 return 类型?哪个可能是这个 metaclass 的 属性?
@property
def type(self):
return type(self.value)
""" changing the type annotation """
type: GetPortType.SAME_2.type
看来您误解了 typing.overload
的作用。它 不会 允许您定义在不同情况下获得 运行 的代码的不同版本。相反,它用于类型提示,以指示 单个 实现支持多种类型组合。 None 的函数重载定义将永远是 运行,它们 仅 为稍后出现的函数的真实版本添加更好的类型提示。
这是一个例子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 to do essentially the same thing as the chain of if
/elif
/else
code above, with a very slightly nicer syntax, but I'm still using 3.9 and I don't feel confident in writing an example for you that I can't test (see PEP 636 获取有关新语句类型的教程。
我正在尝试为 class 创建一个 python 方法,它使用重载类型装饰器。我希望根据传递的枚举类型重载该方法。例如,
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]
我该如何实现?我是否应该为所有这些情况创建枚举和 return 类型的“def __ new __(self, value):”方法?
编辑:我想知道我们是否可以使用 Metaclass 做一些事情,比如值 return 类型?哪个可能是这个 metaclass 的 属性?
@property
def type(self):
return type(self.value)
""" changing the type annotation """
type: GetPortType.SAME_2.type
看来您误解了 typing.overload
的作用。它 不会 允许您定义在不同情况下获得 运行 的代码的不同版本。相反,它用于类型提示,以指示 单个 实现支持多种类型组合。 None 的函数重载定义将永远是 运行,它们 仅 为稍后出现的函数的真实版本添加更好的类型提示。
这是一个例子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 to do essentially the same thing as the chain of if
/elif
/else
code above, with a very slightly nicer syntax, but I'm still using 3.9 and I don't feel confident in writing an example for you that I can't test (see PEP 636 获取有关新语句类型的教程。