Skip to main content
 首页 » 编程设计

python之具有默认枚举值的枚举类方法失败

2024年08月12日31lyj

我很清楚,如果您有一个使用枚举的类名进行类型提示的类方法,则有一个 hack 可以让它在 Python 3.6 及以下版本中工作。

而不是...

class Release(Enum): 
   ... 
   @classmethod 
   def get(cls, release: Release): 
      ... 

你需要像这样使用字符串值...

class Release(Enum): 
   ... 
   @classmethod 
   def get(cls, release: "Release"): 
      ... 

我相信在 Python 3.7 及更高版本中,有一种 pythonic 方式可以绕过这个“hack”,您不必使用引号。原因是“在所有方法和变量首先完成之前,该类还不存在”。由于该类尚不存在,我还不能使用类名,必须使用带引号的字符串作为 hack。

但是,我试图更进一步并使用默认值。那是行不通的。是否有适用于 Python 3.6 的 pythonic 方法不是 hack?此外,python 3.7 及更高版本是否有修复程序?

代码

from enum import Enum 
 
class Release(Enum): 
    Canary = (1, []) 
    Beta = (2, [1]) 
    RC = (3, [2, 1]) 
    Stable = (4, [3, 2, 1]) 
 
    def __new__(cls, value, cascade): 
        obj = object.__new__(cls) 
        obj._value_ = value 
        obj.current = ["Release" * value] # This would technically be a list of all releasese in this enum. This is just to emulate different values 
        obj.cascade = cascade 
        return obj 
 
    @classmethod 
    def get_all_releases(cls, release: "Release" = Canary):  # Default Value = Release.Canary 
        return release.current 
 
 
print(Release.get_all_releases(Release.Canary)) 
print(Release.get_all_releases(Release.Beta)) 
print(Release.get_all_releases(Release.RC)) 
print(Release.get_all_releases(Release.Stable)) 
 
# Error. Even with default value 
# print(Release.get_all_releases()) 

使用这段代码我得到以下错误信息

AttributeError: 'tuple' object has no attribute 'current' 

那是因为它返回的是金丝雀的元组,而不是实际值。

请您参考如下方法:

虽然这绝对是一种解决方法,但它似乎对我很有效:

@classmethod 
def get_all_releases(cls, release: "Release" = Canary):  # Default Value = Release.Canary 
    if release == (Release.Canary.value,): 
        return Release.Canary.current 
    return release.current 

它对您分配给 Canary 的任何值都有效。因此,只要这是您的默认设置,我相信它就会起作用。


为了更通用,您只需调整类定义中的默认值而不是每个函数,您可以按如下方式进行:

class Release(Enum): 
    Canary = 6, 
    Beta = 2, 
    RC = 3, 
    Stable = 4 
    default = Canary 
 
    ... 
 
    @classmethod 
    def get_all_releases(cls, release: "Release" = default): 
        if release == (Release.Canary.value,): 
            return Release.Canary.current 
        return release.current