Reputation: 197
I am creating a simple package called pyma
, available on pypi.
I offer a way to calculate an exponential moving average over N day with a function called NDayEMA(n, data)
. (in fact, it's a class called NDayEMA
, with a function called compute()
but it is irrelevant here.)
I am trying to create a dynamically named function at run-time as shortcut for users.
For example:
NDayEMA(30, data)
and
EMA30(data)
would be the same and
EMA23(data)
EMA1023(data)
EMA12(data)
would also be available.
I understand I will need some reg-ex and processing, which is not required in your answer; I will get it myself! I am searching for how to receive the name of a function provide by the user and create a function with that name without raising error messages.
Here is a PHP equivalent from the Laravel PHP framework.
$user = DB::table('users')->where_email_and_password('[email protected]', 'secret');
Upvotes: 1
Views: 134
Reputation: 64058
I agree with Ari -- what you're trying to do doesn't really bring you any advantages, so probably isn't worth doing.
However, if you absolutely want to, you can abuse module loading/__getattr__
and hack a solution as described in this post.
Basically, if we had a file named foo.py
that looked like this:
def hello(n):
print n
class NDayEMA(object):
def __init__(self, n, day):
self.n = n
self.day = day
Then, you would need to change the contents of foo.py
to look like this:
import sys
class Testing(object):
@staticmethod
def hello(n):
print n
class NDayEMA(object):
def __init__(self, n, day):
self.n = n
self.day = day
def __getattr__(self, attr):
if attr.startswith('EMA'):
n = int(attr[3:])
return lambda day: self.NDayEMA(n, day)
else:
raise AttributeError
sys.modules[__name__] = Testing()
The __getattr__
method is called whenever you attempt to call an attribute or method which is missing within an object. However, there is no such thing as a __getattr__
function that works for modules. Therefore, what we have to do is transform our module into a class, and then replace the module with the class at the very end.
We can now import foo
and do the following:
import foo
foo.hello(3)
a = foo.EMA39('test')
b = foo.EMA1000('test')
print a.n
print b.n
print 'done'
Upvotes: 2
Reputation: 2378
This doesn't exactly answer your question, but I'd recommend against doing what you're asking. You already have a method that takes a number and data as an argument, so turning the number into different method names doesn't seem to be any more convenient than your current method.
Upvotes: 6