在运行时创建动态命名的函数

时间:2014-01-05 20:49:24

标签: python python-2.7

我正在创建一个名为pyma的简单包,可在pypi上找到。

我提供了一种方法,通过一个名为NDayEMA(n, data)的函数计算N天的指数移动平均值。 (事实上​​,它是一个名为NDayEMA的类,有一个名为compute()的函数,但它在这里无关紧要。)

我正在尝试在运行时创建一个动态命名的函数作为用户的快捷方式。

例如:

NDayEMA(30, data) 

EMA30(data)

将是相同的

EMA23(data)
EMA1023(data)
EMA12(data)

也可以。

我知道我需要一些注册和处理,这在你的答案中是不需要的;我自己会得到它!我正在搜索如何接收用户提供的函数的名称,并创建具有该名称的函数,而不会引发错误消息。

这是来自Laravel PHP framework的PHP等效文件。

$user = DB::table('users')->where_email_and_password('example@gmail.com', 'secret');

2 个答案:

答案 0 :(得分:6)

这并不能完全回答你的问题,但我建议你不要做你所要求的。您已经有一个方法将数字和数据作为参数,因此将数字转换为不同的方法名称似乎不比您当前的方法更方便。

答案 1 :(得分:2)

我同意Ari - 你要做的事情并没有给你带来任何好处,所以可能不值得做。

但是,如果你绝对想要,你可以滥用模块加载/ __getattr__并破解解决方案,如post所述。

基本上,如果我们有一个名为foo.py的文件,如下所示:

def hello(n):
    print n

class NDayEMA(object):
    def __init__(self, n, day):
        self.n = n
        self.day = day

然后,您需要将foo.py的内容更改为:

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()

每当您尝试调用对象中缺少的属性或方法时,都会调用__getattr__方法。但是,没有适用于模块的__getattr__函数。因此,我们要做的是将模块转换为类,然后在最后用类替换模块。

我们现在可以导入foo并执行以下操作:

import foo

foo.hello(3)

a = foo.EMA39('test')
b = foo.EMA1000('test')

print a.n
print b.n

print 'done'