带元类的Python类枚举构造

带元类的Python类枚举构造,python,python-3.x,Python,Python 3.x,出于某种原因,在一个星期天的早晨,我觉得我需要为我正在写作的科学图书馆做以下几件事: class PolarityType(type): """Metaclass to construct polarity types. Supports conversion to float and int.""" def __float__(cls): return int(cls) def __int__(cls): return cls.P

出于某种原因,在一个星期天的早晨,我觉得我需要为我正在写作的科学图书馆做以下几件事:

class PolarityType(type):
    """Metaclass to construct polarity types. Supports conversion to float and int."""
    def __float__(cls):
        return int(cls)

    def __int__(cls):
        return cls.P


class Polarity(metaclass=PolarityType):
    """Base class to build polarity."""
    P = 0


class PositivePolarity(Polarity):
    """Positive polarity."""
    P = 1


class NegativePolarity(Polarity):
    """Negative polarity."""
    P = -1

>>> float(NegativePolarity)
>>> -1.0
基本上,我没有传递参数,比如
polarity='POSITIVE'
和检查字符串,也因为我使用类型提示,所以我希望它是强类型的,我编写了上面的代码


有没有更简单/更干净/更好的方法来达到同样的效果?这有意义吗?

您的解决方案可行,但有没有特别的理由不使用

导入枚举
类极性(enum.enum):
正:浮动=1.0
负:浮点=-1.0
定义浮点数(cls):
回归自我价值
定义(cls):
返回int(self.value)
打印(极性.负极,类型(极性.负极))
#极性
打印(类型(极性.负.值),极性.负.值)
#  -1.0
打印(类型(浮动(极性.负极)),浮动(极性.负极))
#  -1.0

您的解决方案可行,但是否有特殊原因不使用

导入枚举
类极性(enum.enum):
正:浮动=1.0
负:浮点=-1.0
定义浮点数(cls):
回归自我价值
定义(cls):
返回int(self.value)
打印(极性.负极,类型(极性.负极))
#极性
打印(类型(极性.负.值),极性.负.值)
#  -1.0
打印(类型(浮动(极性.负极)),浮动(极性.负极))
#  -1.0

有什么原因不能直接使用常规INT进行此操作?也就是说,
NegativePolarity=-1
使用类型系统感觉更健壮,另外,我可以输入提示。我看到人们在层次结构中更进一步,在Haskell中将类型视为值,但在Python中?它甚至没有一个合适的类型检查器。我不确定我是否理解其动机,但如果您想键入hint函数参数,比如说
NegativePolarity
,这与根本不传递此参数有什么区别,因为您知道极性是负的?@Norrius回答您的第二个问题:我会键入hint作为
PolarityType
,例如
def foo(polarity:PolarityType=PositivePolarity):通过
。嗯,好吧,这看起来很合理(mypy也同意)。为了避免元类,您还可以定义类似于
PositivePolarity=polarity(1)
,然后将其用作
def(p:polarity=PositivePolarity):pass
,它与enums非常相似。有没有一个原因你不能只使用常规int来实现这一点?那就是,
NegativePolarity=-1
使用类型系统感觉更健壮,另外,我可以键入提示。我见过人们在Haskell中将类型作为值来处理层次结构,但在Python中?它甚至没有正确的类型e checker.我不确定我是否理解其动机,但如果你想键入一个函数参数,比如说
NegativePolarity
,那与根本不传递这个参数有什么区别,因为你知道极性是负的?@Norrius回答你的第二个问题:我会键入hint作为
PolarityType
,例如
de>f foo(polarity:PolarityType=PositivePolarity):pass
。嗯,好吧,看起来不错(mypy也同意)。为了避免元类,您还可以定义类似于
PositivePolarity=polarity(1)
,然后将其用作
定义f(p:polarity=PositivePolarity):pass
,它与enum非常相似。看起来很棒。我承认我从未使用过
enum
并忘记了它。看起来很棒。我承认我从未使用过
enum
并忘记了它。
import enum

class Polarity(enum.Enum):
    POSITIVE: float = 1.0
    NEGATIVE: float = -1.0

    def __float__(cls):
        return self.value

    def __int__(cls):
        return int(self.value)

print(Polarity.NEGATIVE, type(Polarity.NEGATIVE))
# Polarity.NEGATIVE <enum 'Polarity'>

print(type(Polarity.NEGATIVE.value), Polarity.NEGATIVE.value)
# <class 'float'> -1.0

print(type(float(Polarity.NEGATIVE)), float(Polarity.NEGATIVE))
# <class 'float'> -1.0