I have the following class in Python that I am trying to use for calling a set of its own methods through a dictionary that has the pointers of the available functions:
class Test():
functions = {
'operation_a' : Test.function_a;
'operation_b' : Test.function_b;
}
def run_operations(operation, *args, **kwargs):
try:
functions[str(operation)](self, args, kwargs)
except KeyError:
// some log ...
def function_a(self, *args, **kwargs):
print A
def function_b(self, *args, **kwargs):
print B
This first approach seems to be incorrect since the Python interpreter cannot find class 'Test' (NameError: 'Test' is not defined). I could not find a way (either importing the package, the package and the module, from package.module import *... etc.) Therefore, I have 3 solutions for this issue that already worked for me:
__init__()),However, I still do not know why the initial approach does not seem to be correct. Therefore, how can I reference to a function within the same class before instantiation?
The class object doesn't exist before the end of the class statement's body. But the functions are available in the namespace after the def statement's body. So what you want is:
class Test(object):
def run_operations(self, operation, *args, **kwargs):
try:
function = self.functions[operation]
except KeyError:
# some log ...
else:
function(self, args, kwargs)
def function_a(self, *args, **kwargs):
print "A"
def function_b(self, *args, **kwargs):
print "B"
functions = {
'operation_a' : function_a,
'operation_b' : function_b,
}
edit: As alko mentionned, you could also use getattr with the current instance and method name to get the method, but it means all methods become potential 'operations', which is both unexplicit and a potential security issue. One way to still use getattr with explicit "selection" of the legit operations is to just add a marker to the relevant functions, ie:
def operation(func):
func.is_operation = True
return func
class Test(object):
def run_operations(self, operation, *args, **kwargs):
method = getattr(self, operation, None)
if method is None:
# raise or log or whatever
elif not method.is_operation:
# raise or log or whatever
else:
method(*args, **kwargs)
@operation
def operation_a(self, *args, **kwargs):
print "A"
@operation
def operation_b(self, *args, **kwargs):
print "B"
def not_an_operation(self):
print "not me"
Yet another solution is to use an inner class as namespace for the operations, ie:
class Test(object):
def run_operations(self, operation, *args, **kwargs):
method = getattr(self.operations, operation, None)
if method is None:
# raise or log or whatever
else:
method(self, *args, **kwargs)
class operations(object):
@classmethod
def operation_a(cls, instance, *args, **kwargs):
print "A"
@classmethod
def operation_b(cls, instance, *args, **kwargs):
print "B"
There are still other possible solutions. Which one is "best" depends on your needs, but unless you're building a framework the dict-based one is as simple, readable and effective as possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With