PyWebDesign
PyWebDesign

Reputation: 197

Creating a dynamically named function at runtime

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

Answers (2)

Michael0x2a
Michael0x2a

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

Ari
Ari

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

Related Questions