2014-11-01 7 views
18

उदाहरण:पाइथन एनम्स के साथ तर्कों का नाम इस्तेमाल किया जा सकता है?

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 

रेफरी: https://docs.python.org/3/library/enum.html#planet

क्यों मैं यह कर करना चाहते हैं? यदि कन्स्ट्रक्टर सूची में कुछ आदिम प्रकार (int, bool) हैं, तो नामांकित तर्कों का उपयोग करना अच्छा होगा।

उत्तर

25

आप नामित तर्क जिस तरह से आप enums के साथ वर्णन का उपयोग नहीं कर सकते हैं, आप एक ऐसी ही एक namedtuple mixin साथ प्रभाव प्राप्त कर सकते हैं: ...

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. 

जो मेरे मन को, क्लीनर है आप के बाद से डॉन __init__ विधि लिखना नहीं है।

उदाहरण उपयोग:

>>> Planet.MERCURY 
<Planet.MERCURY: Body(mass=3.303e+23, radius=2439700.0)> 
>>> Planet.EARTH.mass 
5.976e+24 
>>> Planet.VENUS.radius 
6051800.0 

ध्यान दें कि, प्रति the docs के रूप में, "मिश्रण में प्रकार Enum से पहले ही ठिकानों के अनुक्रम में दिखाया जाना चाहिए"।

+0

बहुत शांत। मैंने कभी मिश्रित के साथ समस्या को हल करने पर विचार नहीं किया। – kevinarpe

+2

इंजेनिअस। एक अप-वोट है। :) –

+0

@ ज़ीरोपीरायस: मैंने एक जवाब जोड़ा, लेकिन बक्षीस के लिए नहीं - बस कुछ अप-वोटों की उम्मीद है (मेरे [पायथन-3.x] सोने के बैज के लिए जाने का लंबा रास्ता!)। –

9

@ शून्य-पीरियस द्वारा स्वीकृत उत्तर को डिफ़ॉल्ट तर्कों की अनुमति देने के लिए थोड़ा बढ़ाया जा सकता है। यह बहुत आसान है जब आपके पास एक तत्व के लिए समान मूल्य वाले अधिकांश प्रविष्टियों के साथ एक बड़ा enum है।

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) 

खबरदार अचार बनाने __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 
+0

यह मूल विचार पर एक अच्छा ट्विक है, धन्यवाद! –

+1

अच्छा विस्तार! एक अप-वोट है। :) –

+0

@ शून्य-पीरियस धन्यवाद श्रीमान! –

2

तो namedtuple मिश्रण में से परे जा रहा aenum पुस्तकालय (एक ही साथी है कि stdlib Enum और enum34 backport लिखा द्वारा लिखित) की जाँच करें। Enum के लिए कुछ अतिरिक्त घंटियाँ और सीटी होने के अलावा यह NamedConstant और मेटाक्लास-आधारित NamedTuple का भी समर्थन करता है।

aenum.Enum का उपयोग करते हुए उपरोक्त कोड दिखाई देगा:

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 

और उपयोग में:

--> 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 
संबंधित मुद्दे

 संबंधित मुद्दे