Reputation: 166
I'm trying to use dict as a switch statement in python class like this:
class MyClass:
METHODS_MAP = {} # I want to place map here
# some code here
def caller(self, instructions):
methods_map = {
"a": self.a,
"b": self.b
}
for key, value in instructions.items():
methods_map[key](value)
def a(self, val):
print("Called a")
def b(self, val):
print("Called b")
a = MyClass()
instr = {"b": 12, "a": 14}
a.caller(instr)
Right now it works just fine, but I need to place methods_map
at the same level as method definitions as static variable as some might say. I tried this:
class MyClass:
METHODS_MAP = {
"a": self.a
}
or
class MyClass:
METHODS_MAP = {
"a": a
}
But either way, it doesn't know about class methods. How can I make it work my way?
Upvotes: 0
Views: 164
Reputation: 504
In order to reference methods implemented inside a class the following syntax is required:
METHODS_MAP =
{
'a': MyClass.a,
'b': MyClass.b
}
Because some functions work on class instances and are not @classmethod
s, we need to change the caller()
function:
from inspect import ismethod
def caller(self, instructions):
for key, value in instructions.items():
if METHODS_MAP[key].__self__ is MyClass: # check if function is class method
METHODS_MAP[key](MyClass, value)
elif ismethod(METHODS_MAP[key]): # check if method is an instance method
METHODS_MAP[key](self, value)
else: # static method
METHODS_MAP[key](value)
If the desired function is not a @classmethod
, self
will be passed to it. Else, it will be called as usual
Important note: Although this solution seems more complex than initializing the MEHTODS_MAP
dictionary inside the __init__()
function, it is far less costly. With this method, the number of instances this class has does not affect the number of times METHODS_MAP
will be created in memory (there will always be just one).
With the other method suggested here (using __init__()
), for every instance of MyClass()
a copy of METHODS_MAP
will be needlessly created, since it is initialized inside the __init__()
function
Upvotes: 0
Reputation: 2689
You can add them in the constructor like this:
class MyClass:
def __init__(self):
self.methods_map = {
"a": self.a,
"b": self.b
}
def caller(self, instructions):
for key, value in instructions.items():
self.methods_map[key](value)
def a(self, val):
print("Called a")
def b(self, val):
print("Called b")
x = MyClass()
instr = {"b": 12, "a": 14}
x.caller(instr)
Upvotes: 1