Can named arguments be used with Python enums? Can named arguments be used with Python enums? python python

Can named arguments be used with Python enums?


While you can't use named arguments the way you describe with enums, you can get a similar effect with a namedtuple mixin:

from collections import namedtuplefrom enum import EnumBody = namedtuple("Body", ["mass", "radius"])class Planet(Body, Enum):    MERCURY = Body(mass=3.303e+23, radius=2.4397e6)    VENUS   = Body(mass=4.869e+24, radius=6.0518e6)    EARTH   = Body(mass=5.976e+24, radius=3.3972e6)    # ... etc.

... which to my mind is cleaner, since you don't have to write an __init__ method.

Example use:

>>> Planet.MERCURY<Planet.MERCURY: Body(mass=3.303e+23, radius=2439700.0)>>>> Planet.EARTH.mass5.976e+24>>> Planet.VENUS.radius6051800.0

Note that, as per the docs, "mix-in types must appear before Enum itself in the sequence of bases".


The accepted answer by @zero-piraeus can be slightly extended to allow default arguments as well. This is very handy when you have a large enum with most entries having the same value for an element.

class Body(namedtuple('Body', "mass radius moons")):    def __new__(cls, mass, radius, moons=0):        return super().__new__(cls, mass, radius, moons)    def __getnewargs__(self):        return (self.mass, self.radius, self.moons)class Planet(Body, Enum):    MERCURY = Body(mass=3.303e+23, radius=2.4397e6)    VENUS   = Body(mass=4.869e+24, radius=6.0518e6)    EARTH   = Body(5.976e+24, 3.3972e6, moons=1)

Beware pickling will not work without the __getnewargs__.

class Foo:    def __init__(self):        self.planet = Planet.EARTH  # pickle error in deepcopyfrom copy import deepcopyf1 = Foo()f2 = deepcopy(f1)  # pickle error here


For Python 3.6.1+ the typing.NamedTuple can be used, which also allows for setting default values, which leads to prettier code. The example by @shao.lo then looks like this:

from enum import Enumfrom typing import NamedTupleclass Body(NamedTuple):    mass: float    radius: float    moons: int=0class Planet(Body, Enum):    MERCURY = Body(mass=3.303e+23, radius=2.4397e6)    VENUS   = Body(mass=4.869e+24, radius=6.0518e6)    EARTH   = Body(5.976e+24, 3.3972e6, moons=1)

This also supports pickling. The typing.Any can be used if you don't want to specify the type.

Credit to @monk-time, who's answer here inspired this solution.