首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的动态/运行时方法创建(代码生成)

Python中的动态/运行时方法创建(代码生成)
EN

Stack Overflow用户
提问于 2009-02-10 17:40:06
回答 5查看 51.6K关注 0票数 49

我需要在运行时为一个方法生成代码。能够运行任意代码并拥有文档字符串是很重要的。

我想出了一个结合了execsetattr的解决方案,下面是一个虚拟示例:

代码语言:javascript
复制
class Viking(object):
    def __init__(self):
        code = '''
            def dynamo(self, arg):
                """ dynamo's a dynamic method!
                """
                self.weight += 1
                return arg * self.weight
            '''
        self.weight = 50

        d = {}
        exec code.strip() in d
        setattr(self.__class__, 'dynamo', d['dynamo'])


if __name__ == "__main__":
    v = Viking()
    print v.dynamo(10)
    print v.dynamo(10)
    print v.dynamo.__doc__

有没有更好/更安全/更地道的方法来达到同样的结果?

EN

回答 5

Stack Overflow用户

发布于 2009-02-10 18:38:48

函数文档字符串和名称都是可变属性。您可以在内部函数中做任何您想做的事情,甚至可以有多个版本的内部函数,供makedynamo()在其中进行选择。不需要使用字符串构建任何代码。

下面是解释器中的一段代码:

代码语言:javascript
复制
>>> def makedynamo(i):
...     def innerdynamo():
...         print "in dynamo %d" % i
...     innerdynamo.__doc__ = "docstring for dynamo%d" % i
...     innerdynamo.__name__ = "dynamo%d" % i
...     return innerdynamo

>>> dynamo10 = makedynamo(10)
>>> help(dynamo10)
Help on function dynamo10 in module __main__:

dynamo10()
    docstring for dynamo10
票数 13
EN

Stack Overflow用户

发布于 2009-02-10 18:38:44

Python将允许您在函数中声明函数,因此您不必使用exec技巧。

代码语言:javascript
复制
def __init__(self):

    def dynamo(self, arg):
        """ dynamo's a dynamic method!
        """
        self.weight += 1
        return arg * self.weight
    self.weight = 50

    setattr(self.__class__, 'dynamo', dynamo)

如果您想要该函数的多个版本,您可以将所有这些放入一个循环中,并在setattr函数中更改它们的名称:

代码语言:javascript
复制
def __init__(self):

    for i in range(0,10):

        def dynamo(self, arg, i=i):
            """ dynamo's a dynamic method!
            """
            self.weight += i
            return arg * self.weight

        setattr(self.__class__, 'dynamo_'+i, dynamo)
        self.weight = 50

(我知道这不是很好的代码,但它让人明白了这一点)。至于设置文档字符串,我知道这是可能的,但我必须在文档中查找它。

编辑:您可以通过dynamo.__doc__设置文档字符串,因此您可以在循环体中执行以下操作:

代码语言:javascript
复制
dynamo.__doc__ = "Adds %s to the weight" % i

另一个编辑:在@eliben和@bobince的帮助下,闭包问题应该得到解决。

票数 10
EN

Stack Overflow用户

发布于 2018-02-17 05:48:11

代码语言:javascript
复制
class Dynamo(object):
    def __init__(self):
        pass

    @staticmethod
    def init(initData=None):
        if initData is not None:
            dynamo= Dynamo()
            for name, value in initData.items():
                code = '''
def %s(self, *args, **kwargs):
%s
                            ''' % (name, value)
                result = {}
                exec code.strip() in result
                setattr(dynamo.__class__, name, result[name])

            return dynamo

        return None

service = Dynamo.init({'fnc1':'pass'})
service.fnc1()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/533382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档