Reputation: 469
Is there a way to do something like this in python?
from enum import Enum, auto
def some_func(mode = Mode.A):
class Mode(Enum):
A = auto()
print(mode == Mode.A)
desired outcome
>>> some_func()
True
The above snippet fails with NameError: name 'Mode' is not defined
presumably because class Mode
isn't defined when the interpreter reads def some_func(mode = Mode.A):
You can of course put the Enum outside the function but, if what I propose or something similar worked, I'd rather keep it inside. Keeping it inside encapsulates Mode where it is meant to be used, hopefully allowing .
syntax to distinguish it from other similar Mode
classes.
I am aware that a lot of python code just uses strings for this purpose, not bothering with Enums. However I would like to find a solution using Enums. Enums are easier to maintain and help IDEs generate code completion etc.
Is there a nice way to make this work?
Upvotes: 5
Views: 1549
Reputation: 71454
The caller of a function doesn't have access to locals declared inside the function. Locally-declared classes therefore can't be part of the external interface.
If the enum isn't meant to be accessible by the caller at all, then it shouldn't be accepted as a parameter; just declare and instantiate the enum inside the body of the function and keep it completely hidden from the caller.
If the enum is meant to be accessible by the caller as part of the public interface, it needs to be declared at the same/higher scope as the function itself (i.e. outside of the function).
If you want to encapsulate the function and the enum, a class would be the typical way of doing that (i.e. the function and enum would both be public members of the class).
If you really want to be able to access the enum class as a member of the function you could do something eccentric like:
from enum import Enum, auto
from typing import Optional
class SomeFunc:
class Mode(Enum):
A = auto()
B = auto()
def __call__(self, mode: Optional['Mode'] = None) -> None:
if mode is None:
mode = self.Mode.A
print(mode == self.Mode.A)
some_func = SomeFunc()
some_func()
some_func(some_func.Mode.B)
Upvotes: 5
Reputation: 159
It's working if you first define the enum contents which can be together inside a parent class. You can as well do a type cast to the enum and throw the cast error if a provided string cannot be cast into enum. That would be an accurate way to validate the string input. Haven't written that down, because I don't know if it would help you. Good luck!
# Here the code a bit modified
from enum import Enum, auto
class Parent():
class Mode(Enum):
A = auto()
@staticmethod
def some_func(mode):
print(mode)
Parent.some_func(Parent.Mode.A)
Upvotes: 1