valor - obtener datos de teclado python
¿Se pueden usar los argumentos con nombre con las enumeraciones de Python? (4)
Ejemplo:
class Planet(Enum):
MERCURY = (mass: 3.303e+23, radius: 2.4397e6)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
Ref: https://docs.python.org/3/library/enum.html#planet
¿Por qué quiero hacer esto? Si hay algunos tipos primitivos (int, bool) en la lista de constructores, sería bueno usar argumentos con nombre.
La respuesta aceptada por @ zero-piraeus puede extenderse ligeramente para permitir argumentos predeterminados también. Esto es muy útil cuando tiene una enumeración grande con la mayoría de las entradas que tienen el mismo valor para un elemento.
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)
Cuidado con el decapado no funcionará sin el __getnewargs__
.
class Foo:
def __init__(self):
self.planet = Planet.EARTH # pickle error in deepcopy
from copy import deepcopy
f1 = Foo()
f2 = deepcopy(f1) # pickle error here
Para Python 3.6.1+, se puede usar typing.NamedTuple , que también permite establecer valores predeterminados, lo que lleva a un código más bonito. El ejemplo de @ shao.lo se ve así:
from enum import Enum
from typing import NamedTuple
class Body(NamedTuple):
mass: float
radius: float
moons: int=0
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)
Esto también apoya el decapado. La escritura. Cualquiera puede usarse si no desea especificar el tipo.
Gracias a @ monk-time, quien respondió here inspiró esta solución.
Si bien no puede usar los argumentos con nombre de la forma en que lo describe con las enumeraciones, puede obtener un efecto similar con un mixin con namedtuple
:
from collections import namedtuple
from enum import Enum
Body = 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.
... lo que en mi opinión es más limpio, ya que no tiene que escribir un método __init__
.
Ejemplo de uso:
>>> Planet.MERCURY
<Planet.MERCURY: Body(mass=3.303e+23, radius=2439700.0)>
>>> Planet.EARTH.mass
5.976e+24
>>> Planet.VENUS.radius
6051800.0
Tenga en cuenta que, según los documentos , "los tipos de mezcla deben aparecer antes de Enum
en la secuencia de bases".
Si va más allá de la mezcla de elementos namedtuple
, consulte la biblioteca aenum
1 . Además de tener algunas campanas y silbidos adicionales para Enum
, también es compatible con NamedConstant
y NamedTuple
basado en NamedTuple
.
El uso de aenum.Enum
el código anterior podría verse así:
from aenum import Enum, enum, _reduce_ex_by_name
class Planet(Enum, init=''mass radius''):
MERCURY = enum(mass=3.303e+23, radius=2.4397e6)
VENUS = enum(mass=4.869e+24, radius=6.0518e6)
EARTH = enum(mass=5.976e+24, radius=3.3972e6)
# replace __reduce_ex__ so pickling works
__reduce_ex__ = _reduce_ex_by_name
y en uso:
--> for p in Planet:
... print(repr(p))
<Planet.MERCURY: enum(radius=2439700.0, mass=3.3030000000000001e+23)>
<Planet.EARTH: enum(radius=3397200.0, mass=5.9760000000000004e+24)>
<Planet.VENUS: enum(radius=6051800.0, mass=4.8690000000000001e+24)>
--> print(Planet.VENUS.mass)
4.869e+24
1 Divulgación: Soy el autor de Python stdlib Enum
, el enum34
backport y la biblioteca de aenum .