You shouldn't be using a class in the first place. All you are doing is creating a namespace, use a module for that. Create a new module in a package and put all your functions in that:
def _a():
print("A")
def _b():
print("B")
ACTIONS = {
'ACTION_A': _a,
'ACTION_B': _b,
}
def do(constant):
ACTIONS[constant]()
Note that I used single underscore names. Python uses double-underscore names in classes to create an additional per-class namespace. MyClass.__a
becomes MyClass._MyClass__a
to avoid clashes with subclasses (so they can freely re-use names without fear of breaking the implentation of a superclass), there is no privacy model in Python.
You could use a decorator to register the _a
and _b
functions:
def do(constant):
ACTIONS[constant]()
ACTIONS = {}
def action(name):
def decorator(f):
ACTIONS[name] = f
return f
@action('ACTION_A')
def _a():
print("A")
@action('ACTION_B')
def _b()
print("B")
The specific error you see is due to the MyClass
name not being set until the whole class
statement has completed. You'd have to set that dictionary afterwards:
class MyClass:
@classmethod
def do(cls, constant):
cls.ACTIONS[constant]()
@staticmethod
def _a():
print("A")
@staticmethod
def _b():
print("B")
MyClass.ACTIONS = {
'ACTION_A': MyClass._a,
'ACTION_B': MyClass._b,
}
Note that do
is a class method, you can't just access ACTIONS
as a global, you need to use either MyClass.ACTIONS
or, as I used above, a class method then reference the object on cls
.
You could work around having to set ACTIONS
after the class
statement by using names instead, and make def do
a class method:
class MyClass:
ACTIONS = {
'ACTION_A': '_a',
'ACTION_B': '_b',
}
@classmethod
def do(cls, constant):
getattr(cls, cls.ACTIONS[constant])()
@staticmethod
def _a():
print("A")
@staticmethod
def _b():
print("B")