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

2024-05-19 05:20:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要在运行时为方法生成代码。能够运行任意代码并拥有docstring是很重要的。

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

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__

有没有更好/更安全/更惯用的方法来达到同样的效果?


Tags: 方法代码selfdefargcode解决方案class
3条回答

Python将允许您在函数中声明一个函数,因此不必进行exec技巧。

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函数中更改它们的名称:

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

(我知道这不是很好的代码,但它能说明问题)。至于设置docstring,我知道这是可能的,但我必须在文档中查找它。

编辑:可以通过dynamo.__doc__设置docstring,这样就可以在循环体中执行类似的操作:

dynamo.__doc__ = "Adds %s to the weight" % i

另一次编辑:在@eliben和@bobince的帮助下,应该解决关闭问题。

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

以下是解释器中的一个片段:

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

基于Theran的代码,但将其扩展到类上的方法:



class Dynamo(object):
    pass

def add_dynamo(cls,i):
    def innerdynamo(self):
        print "in dynamo %d" % i
    innerdynamo.__doc__ = "docstring for dynamo%d" % i
    innerdynamo.__name__ = "dynamo%d" % i
    setattr(cls,innerdynamo.__name__,innerdynamo)

for i in range(2):
    add_dynamo(Dynamo, i)

d=Dynamo()
d.dynamo0()
d.dynamo1()

应打印:


in dynamo 0
in dynamo 1

相关问题 更多 >

    热门问题