Sample code file:
MyCode.py
def DoSomething(data):
# data is a string
# find a function in the same scope as this one that has the name contained
# in "data"
try:
func = getattr(self,data) # this is wrong
except AttributeError:
print "Couldn't find function %s." % data
return
# execute the function
func()
def AFunction():
print "You found a function!"
def Add():
print "1 + 1 = %d." % ( (1+1) )
def test():
# unit test
DoSomething("AFunction")
--------
test.py
import MyCode
# Try executing some functions
MyCode.DoSomething("AFunction") # should print You found a function!
MyCode.DoSomething("Add") # should print 1+1=2.
MyCode.DoSomething("IDoNotExist") # should run the exception handler
# Try executing a function from inside the module
MyCode.test() # should print You found a function!
If I were dealing with a class object, that getattr
statement would end up retrieving a reference to the function within the class that matches the name provided. Then, as shown, I could execute that function directly from its variable name.
However, since these functions are NOT in a class, rather they are at the module/file level, using getattr
on self won't work since we don't have a self
reference into a class instance.
My question is: is it actually necessary to wrap this function along with all its supporting functions in a class and instantiate that class just to have this capability? Or, is there an alternative way to use getattr
so that I can access the functions defined at the file level.
Notice both use cases: Within the file itself, the "test" function needs to call these functions, but also from outside as imported the function that runs arbitrary other functions might need to run.
Advice appreciated.
Thanks!
import sys
current_module = sys.modules[__name__]
getattr(current_module, 'AFunction')
Wrapping everything with a class will be more secure though.
getattr
works on any object, and in Python mostly everything is an object, including classes and modules. So from a purely technical POV you can either store your functions in a class (probably as staticmethods
) and use getattr
on that class, or even use the hack posted by freakish to directly retrieve them from the module.
BUT...
But it's not the RightWay(tm) to solve your problem.
In it's simplest form, an object (class, instance, module, whatever) is mostly the combination of a dict
, a class and the attribute resolution operator - which quite often ends up doing a simple lookup on one dict or another (ie the instance's dict, the class's dict, then the parents classes etc). In your above example, all you need is a simple dict lookup, and the obvious solution is, well, to use a plain old dict - remember, in Python everything is an object, including functions:
MyCode.py
FUNCTIONS = {}
def DoSomething(data):
# data is a string
# find a function in the same scope as this one that has the name contained
# in "data"
func = FUNCTIONS.get(data)
if func is None:
print "Couldn't find function %s." % data
return
# execute the function
func()
def AFunction():
print "You found a function!"
FUNCTIONS["AFunction"] = AFunction
def Add():
print "1 + 1 = %d." % ( (1+1) )
FUNCTIONS["Add"] = Add
def test():
# unit test
DoSomething("AFunction")
Now you may find the FUNCTIONS["whatever"] = whatever
pattern a bit boring - but hopefully we can make it a bit more sexy thanks to the decorator syntax:
FUNCTIONS = {}
def register(func):
FUNCTIONS[func.__name__] = func
return func
def DoSomething(data):
# data is a string
# find a function in the same scope as this one that has the name contained
# in "data"
func = FUNCTIONS.get(data)
if func is None:
print "Couldn't find function %s." % data
return
# execute the function
func()
@register
def AFunction():
print "You found a function!"
@register
def Add():
print "1 + 1 = %d." % ( (1+1) )
As an added benefit: you have complete control AND some automatic documentation of which functions are supposed to be accessible thru DoSomething()
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