Macro-Powered Enums
Hey All, I know this ship has already sailed with PEP 435, but I've been working on a prototype implementation of enums using MacroPy macros<https://github.com/lihaoyi/macropy#enums> . The goal was to have enums whose methods provide most of the nice capabilities of int enums (auto-generated indexes, fast comparison, incrementing, index-arithmetic, find-by-index) and string enums (nice __repr__, find-by-name) but has the ability to smoothly scale to full-fledged objects with methods *and* fields, all this is an extremely concise way. The gimmick here is that it uses macros to provide a concise syntax to allow you to construct each enum instance with whatever constructor parameters you wish, java-enum-style (here<https://github.com/lihaoyi/macropy#complex-enums>). This allows a degree of enums-as-objects which i haven't seen in any other library (most don't allow custom fields). Probably not standard-library worthy, but I thought it was pretty cool. -Haoyi
On 07/05/2013 05:56 PM, Haoyi Li wrote:
I know this ship has already sailed with PEP 435, but I've been working on a prototype implementation of enums using MacroPy macros <https://github.com/lihaoyi/macropy#enums>.
The goal was to have enums whose methods provide most of the nice capabilities of int enums (auto-generated indexes, fast comparison, incrementing, index-arithmetic, find-by-index) and string enums (nice __repr__, find-by-name) but has the ability to smoothly scale to full-fledged objects with methods *and* fields, all this is an extremely concise way.
The stdlib Enum and IntEnum offer this already, although not quite as concisely (I haven't looked at your macro code to see how it handles the missing name lookup, but in standard Python that "feature" invites way too many bugs).
The gimmick here is that it uses macros to provide a concise syntax to allow you to construct each enum instance with whatever constructor parameters you wish, java-enum-style (here <https://github.com/lihaoyi/macropy#complex-enums>). This allows a degree of enums-as-objects which i haven't seen in any other library (most don't allow custom fields).
Check out the stdlib Enum -- I think you'll be pleasantly suprised!
Probably not standard-library worthy, but I thought it was pretty cool.
It is indeed cool. For comparison, here is your complex Direction Enum in stdlib syntax: -- 8< ---------------------------------------------------------------------- from enum import Enum class Direction(Enum): """stdlib version of MacroPy complex Directions Enum""" __order__ = 'North East South West' # for 2.x North = ("Vertical", ["Northrend"]) East = ("Horizontal", ["Azeroth", "Khaz Modan", "Lordaeron"]) South = ("Vertical", ["Pandaria"]) West = ("Horizontal", ["Kalimdor"]) def __new__(cls, *args): "__new__ can be omitted if you don't want int-like behavior" value = len(cls.__members__) + 1 obj = object.__new__(cls) obj._value = value return obj def __init__(self, alignment, continent): self.alignment = alignment self.continent = continent def __int__(self): "__int__ can be omitted if you don't want int-like behavior" return self.value def __index__(self): return self.value @property def opposite(self): return Direction((self.value + 2) % 4) def padded_name(self, n): return ("<" * n) + self.name + (">" * n) # members print(Direction.North.alignment) # Vertical print(Direction.East.continent) # ["Azeroth", "Khaz Modan", "Lordaeron"] # properties print(Direction.North.opposite) # Direction.South # methods print(Direction.South.padded_name(2)) # <<South>> # int-like print(int(Direction.East)) # 1 print(('zero', 'one', 'two', 'three', 'four')[Direction.South]) # 'three' -- 8< ---------------------------------------------------------------------- Over half the code goes away if you don't need the int-like behavior. Oh, and the `__order__` is only used in the PyPI version (enum34) so that 2.x enums can still have a "definition" order. -- ~Ethan~
participants (2)
-
Ethan Furman
-
Haoyi Li