はじめに
どうも、水無月せきなです。
最近Pythonをちょこちょこ使用しているのですが、その中で驚いた話についてです。
Pythonの列挙型
Pythonで列挙型を普通に使用すると下記のようになります。
(例は公式から拝借)
from enum import Enum
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
ここからが驚いたポイントなのですが、列挙型の値にはタプルも指定できます。
class Sample(Enum):
HOGE = ("hoge", 1)
FUGA = ("fuga", 2)
そのままだと.valueにタプルの値が入りますが、この挙動は__new__で変更できます。
※__init__でもできそうですが、__new__を使うべき、っぽいです。
__new__() must be used whenever you want to customize the actual value of the Enum member. Any other modifications may go in either __new__() or __init__(), with __init__() being preferred.
class Coordinate(bytes, Enum):
"""
Coordinate with binary codes that can be indexed by the int code.
"""
def __new__(cls, value, label, unit):
obj = bytes.__new__(cls, [value])
obj._value_ = value
obj.label = label
obj.unit = unit
return obj
PX = (0, 'P.X', 'km')
PY = (1, 'P.Y', 'km')
VX = (2, 'V.X', 'km/s')
VY = (3, 'V.Y', 'km/s')
タプルの値を分解して参照する場合
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
# universal gravitational constant (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
おわりに
個人的に意外な仕様についてでした。
実装で使ってみたことはあるのですが、やりすぎるとわけがわからなくなりそうで、使い所ってどこなのだろうと思ったりしています。
ここまでお読みいただきありがとうございました。ご参考になれば幸いです。