如何根据 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 获取有关新语句类型的教程。