This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author killerrex
Recipients killerrex
Date 2018-05-07.10:02:37
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1525687357.98.0.682650639539.issue33437@psf.upfronthosting.co.za>
In-reply-to
Content
I have to read and write many files for an old fortran program where the elements are coded as integer (so 0 is the X, 1 is the Y...) and I have some tags associated to each one.

So I tried to create an Enum with some additional fields:
class Coord(Enum):
    def __init__(self, value, label, unit):
        super().__init__()
        self._value_ = value
        self.label = label
        self.unit = unit

    PX = (0, 'P.X', 'km')
    PY = (1, 'P.Y', 'km')
    VX = (2, 'V.X', 'km/s')
    VY = (3, 'V.Y', 'km/s')

This almost work:
>>> for element in CoordOk:
...    print("{0}: {0.label}[{0.unit}] = {0.value}".format(element))
CoordOk.PX: P.X[km] = 0
CoordOk.PY: P.Y[km] = 1
CoordOk.VX: V.X[km/s] = 2
CoordOk.VY: V.Y[km/s] = 3

But fails recovering the coordinate from the value:
>>> print(Coord(0))
Traceback (most recent call last):
  File "/home/killerrex/tmp/demo.py", line 33, in <module>
    print(Coord(0))
  File "/usr/lib64/python3.6/enum.py", line 291, in __call__
    return cls.__new__(cls, value)
  File "/usr/lib64/python3.6/enum.py", line 533, in __new__
    return cls._missing_(value)
  File "/usr/lib64/python3.6/enum.py", line 546, in _missing_
    raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 0 is not a valid Coord

Because the internal value of the enum is (0, 'P.X', 'km') and not 0

I found that it is possible to do what I am trying to do with:
class CoordOk(Enum):
    def __new__(cls, value, label, unit):
        obj = object.__new__(cls)
        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')

Following the latest doc from Enum. Although it is not so intuitive (defining __new__ is not as easy as __init__)

To make the first proposal work fine is enough with moving the line 221 of enum.py after the line 224 (see the patch)
I haven't found problems with the change but obviously my little reduced tests are not representative at all.
And even if it works there may be good reasons to not allow changing the _value_ in the init.

So mi enhancement proposal is either:
Add an example like the CoordOk to the documentation to help others to find how to change the _value_ (and an explanation on why is better not to do it in the __init__ would be perfect)

or

Change the line enum.py so it is possible to update the _value_ in the __init__ method and if you want use the Coord example in the docs.

Thanks!
History
Date User Action Args
2018-05-07 10:02:38killerrexsetrecipients: + killerrex
2018-05-07 10:02:37killerrexsetmessageid: <1525687357.98.0.682650639539.issue33437@psf.upfronthosting.co.za>
2018-05-07 10:02:37killerrexlinkissue33437 messages
2018-05-07 10:02:37killerrexcreate