Back to Blog
Python

Using python enum auto for Automatic Values

Learn how python enum auto assigns values automatically, how to customize value generation, and when to use it for cleaner, more maintainable enums.

Enumauto()PythonCode GenerationMaintainability
Illustration of Python enum members being assigned sequential values automatically by the auto() function

python enum auto requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

When you define an enum in Python, each member normally needs an explicit value. For many enums the actual numeric value is irrelevant; you only care about the member names. Writing out 1, 2, 3 by hand adds noise and invites mistakes when you insert a new member in the middle. The auto() helper from the enum module solves this by generating values for you. Here is a minimal example:

from enum import Enum, auto class Color(Enum): RED = auto() GREEN = auto() BLUE = auto()

Each member gets a unique integer value starting at 1, in the order they are defined. Color.RED.value is 1, Color.GREEN.value is 2, and so on. This is the simplest way to use python enum auto, and it is the right choice whenever the exact value carries no domain meaning.

How auto() Assigns Values

The default behavior of auto() is controlled by a class method called _generate_next_value_. The enum module calls this method once for each member that uses auto(), at class definition time. The default implementation returns start + count, where start defaults to 1 and count is the number of auto() calls already processed. This means values are assigned sequentially, starting at 1, regardless of explicit values you may have set on other members.

class Status(Enum): PENDING = 0 ACTIVE = auto() # gets 1 DISABLED = auto() # gets 2

Here PENDING is explicitly 0, but ACTIVE still gets 1 because auto() starts its own counter. If you want the auto values to follow an explicit value, you need to override _generate_next_value_ or use a different start parameter, which we will cover shortly.

Using auto() with IntEnum and StrEnum

auto() works with any Enum subclass, including IntEnum and StrEnum. With IntEnum, the generated values are integers and can be used in comparisons or as array indices. With StrEnum (available from Python 3.11), auto() generates string values by using the member name as the value.

from enum import IntEnum, StrEnum, auto class Priority(IntEnum): LOW = auto() # 1 MEDIUM = auto() # 2 HIGH = auto() # 3 class Direction(StrEnum): NORTH = auto() # "NORTH" SOUTH = auto() # "SOUTH"

For StrEnum, the default _generate_next_value_ returns the member name itself, not an integer. This is useful when you need to serialize the enum to a string and want the value to match the name. The mechanism is the same: the method is called once per auto() member, and you can override it to change the pattern.

Customizing Value Generation

If the default sequential integers do not fit your needs, override _generate_next_value_ in your enum class. The method receives four arguments:

  • name: the member name
  • start: the start value passed to Enum (default 1)
  • count: the number of auto() calls so far
  • last_values: a list of the values of all previously defined members (including explicit ones)

A common customization is to start from a different number or to use a step other than 1.

class Port(Enum): def _generate_next_value_(name, start, count, last_values): return start + count * 2 HTTP = auto() # 1 HTTPS = auto() # 3 FTP = auto() # 5

Here start defaults to 1, and count increments by 1 for each auto() call, so the values become 1, 3, 5. You can also use last_values to base the next value on the previous member's value, which is useful when you mix explicit and auto values.

class Offset(Enum): def _generate_next_value_(name, start, count, last_values): return last_values[-1] + 10 if last_values else start A = 100 B = auto() # 110 C = auto() # 120

This approach gives you fine control while still avoiding manual repetition. Overriding _generate_next_value_ is a class method, so it applies to every auto() call in that enum.

Mixing Explicit Values and auto()

You can mix explicit values and auto() in the same enum, but the interaction can be surprising. The default counter for auto() does not reset when it encounters an explicit value. It only counts the number of auto() calls. This means that if you define an explicit value after an auto() member, the next auto() will continue from the previous auto() value, not from the explicit one.

class Example(Enum): A = auto() # 1 B = 10 C = auto() # 2, not 11

If you need C to follow B, you must override _generate_next_value_ to look at last_values and compute from the last defined value. The default behavior is designed for enums where all members use auto() or where explicit values are independent. Mixing them without understanding this can lead to duplicate values or values that do not match your intent.

Runtime Cost and Maintainability

auto() is evaluated at class definition time, not at runtime. There is no per-access overhead; the generated values are stored as normal enum member values. The only cost is the one-time call to _generate_next_value_ for each auto() member when the class is created, which is negligible.

From a maintainability perspective, auto() reduces duplication and makes it easier to insert new members. If you add a member in the middle of an enum with explicit sequential integers, you must renumber all subsequent members. With auto(), the values adjust automatically. However, if the enum values are part of a stable public API (for example, persisted in a database or used in a wire protocol), explicit values are safer because they do not change when members are reordered or removed. auto() is best for internal enums where the exact value is irrelevant.

Compatibility and Version Considerations

auto() was introduced in Python 3.6. If you are using an older version, you cannot rely on it. The StrEnum class, on the other hand, is only available from Python 3.11. For projects that support multiple Python versions, you can use auto() with a regular Enum or IntEnum without issue, but StrEnum requires a version check or a backport. The behavior of _generate_next_value_ is stable across versions, but always verify the Python version in your environment if you depend on a specific generation pattern.

Overriding the Start Value

The Enum constructor accepts a start parameter that changes the initial value for auto(). This is a simple way to start from a different number without overriding _generate_next_value_.

class ErrorCode(Enum): def __init__(self, code): self.code = code A = auto() B = auto() C = auto() # Use start=1000 ErrorCode = Enum('ErrorCode', ['A', 'B', 'C'], start=1000)

In this functional API form, the start argument is passed directly. The values become 1000, 1001, 1002. This is useful when you need a range that does not collide with other constants. For the class syntax, you can pass start to the Enum metaclass by defining _ignore_ or using a custom base, but the functional API is the simplest way to set a custom start.

When Not to Use auto()

auto() is not suitable for enums where the value carries semantic meaning, such as HTTP status codes or bit flags. In those cases, explicit values make the code self-documenting and prevent accidental changes. For example, an enum representing HTTP status codes should use 200 = OK, 404 = NOT_FOUND, not auto(). Similarly, if you are serializing enum values to a database, you want stable integers that do not shift when you add a new member. Use auto() only when the value is an implementation detail and the member name is the primary identity.

python enum auto: Automatic Values in Python Enums | RYUSLOG DEV