Enums¶
from macropy.case_classes import macros, enum
@enum
class Direction:
North, South, East, West
print(Direction(name="North")) # Direction.North
print(Direction.South.name) # South
print(Direction(id=2)) # Direction.East
print(Direction.West.id) # 3
print(Direction.North.next) # Direction.South
print(Direction.West.prev) # Direction.East
print(Direction.all)
# [Direction.North, Direction.East, Direction.South, Direction.West]
MacroPy also provides an implementation of Enumerations , heavily inspired by the Java implementation and built upon Case Classes. These are effectively case classes with:
- A fixed set of instances;
- Auto-generated
name
,id
,next
andprev
fields; - Auto-generated
all
list, which enumerates all instances; - A
__new__
method that retrieves an existing instance, rather than creating new ones
Note that instances of an Enum cannot be created manually: calls such
as Direction(name="North")
or Direction(id=2)
attempt to retrieve
an existing Enum with that property, throwing an exception if there is
none. This means that reference equality is always used to compare
instances of Enums for equality, allowing for much faster equality
checks than if you had used Case Classes.
Definition of Instances¶
The instances of an Enum can be declared on a single line, as in the example above, or they can be declared on subsequent lines:
@enum
class Direction:
North
South
East
West
or in a mix of the two styles:
@enum
class Direction:
North, South
East, West
The basic rule here is that the body of an Enum can only contain bare names, function calls (show below), tuples of these, or function defs: no other statements are allowed. In turn the bare names and function calls are turned into instances of the Enum, while function defs (shown later) are turned into their methods. This also means that unlike Case Classes, Enums cannot have a body initializer.
Complex Enums¶
@enum
class Direction(alignment, continents):
North("Vertical", ["Northrend"])
East("Horizontal", ["Azeroth", "Khaz Modan", "Lordaeron"])
South("Vertical", ["Pandaria"])
West("Horizontal", ["Kalimdor"])
@property
def opposite(self):
return Direction(id=(self.id + 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>>
Enums are not limited to the auto-generated members shown above. Apart from the fact that Enums have no constructor, and no body initializer, they can contain fields, methods and properties just like Case Classes do. This allows you to associate arbitrary data with each instance of the Enum, and have them perform as full-fledged objects rather than fancy integers.