Recently I came up with an interesting trick for a simpler and perhaps more intuitive (especially for beginners) way to call a Python function that take enums as an arguments.

Here is a sample code:

from graphics_2d_library import draw_pixel

draw_pixel(
    x=10,
    y=10,
    color=draw_pixel.color.BLUE  # colors are always on hand
)

graphics_2d_library module implementation:

from enum import Enum


class Color(Enum):
    RED = "red"
    GREEN = "green"
    BLUE = "blue"


def draw_pixel(x, y, color=Color.RED):
    print(f"Drawing pixel at (x={x}, y={y}) with color: {color}")


draw_pixel.color = Color  # here we bind draw_pixel function and Color enum

Pay attention to the last line of code: since Python function is also an object, you can add any attributes to it.

Autocomplete works too:

VS Code autocomplete shows Color enum options when typing draw_line.colors.

Owned enum

As a pioneer, I give the name of this trick - “Owned enum” (but open to your suggestions)

This can be a convention, when followed - enables better code collocation and reduce number of entities to import. Here is another example:

from graphics_2d_library import draw_pixel, draw_line

draw_pixel(
    x=10,
    y=10,
    color=draw_pixel.color.BLUE
)

draw_line(
    start_x=0,
    start_y=0,
    end_x=10,
    end_y=10,
    color=draw_line.color.BLUE,
    style=draw_line.style.DASHED,
)

Alternative?

Of course, you can use type hints, but you would still need to import enum Color.

from graphics_2d_library import draw_pixel, Color

draw_pixel(
    x=10, 
    y=10,
    color=Color.BLUE
)

Alternative implementation of the graphics_2d_library module (without owned enum)

from enum import Enum


class Color(Enum):
    RED = "red"
    GREEN = "green"
    BLUE = "blue"


def draw_pixel(x, y, color: Color = Color.BLUE):
    print(f"Drawing pixel at ({x}, {y}) with color: {color}")

Inspiration and Prior work

It was inspired by the syntax of JSX namespaces, which were added to React version 0.11.0, back in 2014 (!). I think the first time that I saw them in Semantic UI React documentation, they’ve been using this approach since 2015.

The Radix UI documentation also provides a good example:

const PopoverDemo = () => (
  <Popover.Root>
    <Popover.Trigger>More info</Popover.Trigger>
    <Popover.Portal>
      <Popover.Content>
        Some more info
        <Popover.Arrow />
      </Popover.Content>
    </Popover.Portal>
  </Popover.Root>
);

Discussion

Link to Reddit discussion r/Python

Link to Reddit discussion r/learnpython