从构造函数中选择枚举值?

2024-10-01 17:38:18 发布

您现在位置:Python中文网/ 问答频道 /正文

扩展Enum示例here,我可以添加一个类方法,在只提供其元组的一部分时选择正确的枚举:

class Planet1(Enum):
    MERCURY = (3.303e23, 2.4397e6)
    VENUS = (4.869e24, 6.0518e6)
    EARTH = (5.976e24, 6.37814e6)
    MARS = (6.421e23, 3.3972e6)

    @classmethod
    def from_partial(cls, mass=None, radius=None):
        for member in cls:
            if member.mass == mass or member.radius == radius:
                return member
        raise ValueError("No planet with these characteristics.")

    def __init__(self, mass, radius):
        self.mass = mass  # in kg
        self.radius = radius  # in m

p1 = Planet1.MARS
p2 = Planet1.from_partial(6.421e23)
p3 = Planet1.from_partial(radius=3.3972e6)
p1 is p2 is p3  # True

我希望能够在不使用.from_partial()方法的情况下选择一个。有可能吗?

我所尝试的:

class Planet2(Enum):
    MERCURY = (3.303e23, 2.4397e6)
    VENUS = (4.869e24, 6.0518e6)
    EARTH = (5.976e24, 6.37814e6)
    MARS = (6.421e23, 3.3972e6)

    def __init__(self, mass=None, radius= None):
        if mass is None or radius is None:
            for member in Planet2:
                if member.mass == mass or member.radius == radius:
                    self.__dict__ = member.__dict__
        else:
            self.mass = mass  # in kg
            self.radius = radius  # in m

p2a = Planet2.MARS
p2b = Planet2(6.421e23)  # ValueError: 6.421e+23 is not a valid Planet2
p2c = Planet2(radius=3.3972e6) # TypeError: __call__() got an unexpected keyword argument 'radius'

有没有办法做到这一点,或者这是否违背了枚举的用途?这个self.__dict__ = member.__dict__看起来很狡猾,但我原以为它会奏效:)


Tags: infromselfnoneispartialmassmember
2条回答

编辑更新的问题:

您可以得到的最接近的选项是下面的选项2,但是您只能指定一个值,而不能指定您想要的值(因此没有关键字参数)

考虑到这一点,我将坚持使用单独的from_partial()类方法


根据您的用例,您有两个选择:

  1. 编写自己的__new__并为_value_分配一个数字,以及其他任何属性:
    class Planet(Enum):
        #
        def __new__(cls, mass):
            value = len(cls.__members__) + 1
            member = object.__new__(cls)
            member._value_ = value
            member.mass = mass
            return obj
        #
        MERCURY = 3.303e23
        VENUS = 4.869e24
        EARTH = 5.976e24
        MARS = 6.421e23
  1. 从Python 3.6开始,您可以添加一个_missing_方法来代替from_num
    class Planet(Enum):
        #
        @classmethod
        def _missing_(cls, value):
            for member in cls:
                if member._value_[0] == value:
                    return member
        #
        MERCURY = 1, 3.303e23
        VENUS = 2, 4.869e24
        EARTH = 3, 5.976e24
        MARS = 4, 6.421e23

披露:我是Python stdlib ^{}^{} backportAdvanced Enumeration (^{})图书馆的作者

Enum值应该是(理想情况下是不透明的)整数,因此您的使用不符合预期。例如,如果创建正确,Planet(3)确实有效:

from enum import Enum

class Planet(Enum):
    MERCURY = 1
    VENUS = 2
    EARTH = 3
    MARS = 4

class Planets:

    def __init__(self):
        ordered_masses = 3.303e23, 4.869e24, 5.976e24, 6.421e23
        self._data = dict((Planet(i),m) for i,m in enumerate(ordered_masses,1))

    def mass(self,planet):
        return _data[planet]

    def display(self):
        for k,v in self._data.items():
            print(k,v)

print(Planet(3))
Planets().display()

输出:

Planet.EARTH
Planet.MERCURY 3.303e+23
Planet.VENUS 4.869e+24
Planet.EARTH 5.976e+24
Planet.MARS 6.421e+23

相关问题 更多 >

    热门问题