在Python中的动态/运行时方法创建(代码生成)
在Python中的动态/运行时方法创建(代码生成)
我需要在运行时生成一个方法的代码。能够运行任意代码并且有一个文档字符串是很重要的。\n我想出了一个结合了exec
和setattr
的解决方案,这是一个虚拟的例子:\n
class Viking(object): def __init__(self): code = ''' def dynamo(self, arg): """ dynamo是一个动态方法! """ 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__
\n是否有更好/更安全/更符合惯用方式的方法来实现相同的结果?
在Python中,可以在一个函数内部声明另一个函数,因此不需要使用exec
技巧。
如果想要有多个函数的版本,可以将所有内容放在一个循环中,并在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
至于设置文档字符串,我知道这是可能的,但我需要在文档中查找。
编辑:您可以通过dynamo.__doc__
设置文档字符串,因此您可以在循环体中执行以下操作:
dynamo.__doc__ = "Adds %s to the weight" % i
另一个编辑:在和的帮助下,封闭问题应该得到解决。
一旦循环结束,每个dynamo实例中的‘i’都将为10。变量在每次循环时不会重新绑定。这是在Python(和其他类似的语言)中使用闭包的一个重要注意事项。
啊,糟糕。感谢澄清。有没有一种可以解决这个问题的技术呢?
Justin,关于解决这个问题的技术,请参考:stackoverflow.com/questions/233673/…
动态/运行时方法创建(代码生成)在Python中的出现原因是函数的docstring和名称是可变的属性。在内部函数中,你可以做任何你想做的事情,甚至可以有多个版本的内部函数,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
解决方法是在内部函数中使用`__doc__`和`__name__`属性来动态设置docstring和名称。
动态/运行时方法创建(代码生成)在Python中的出现的原因是为了在类上创建方法。原有的代码是基于Theran的代码进行扩展的,用于在类上添加方法。代码中的add_dynamo函数用于为类动态添加方法。代码中的for循环用于多次调用add_dynamo函数,实现了动态创建多个方法的功能。最后,通过创建Dynamo类的实例d,并调用新增的方法d.dynamo0和d.dynamo1,验证了方法动态创建的成功。
为了实现动态创建方法,代码中使用了setattr函数,该函数用于给类动态添加属性。通过设置属性的名称为方法的名称,属性的值为方法的定义,实现了方法的动态创建。
通过在innerdynamo函数中添加_decorator装饰器,可以为每个方法添加装饰器。但是根据提问者的描述,添加装饰器的尝试并未成功,原因可能是其他问题,需要更多信息来确定具体原因。
总结起来,动态/运行时方法创建在Python中的出现是为了在类上动态添加方法。通过使用setattr函数,可以实现方法的动态创建。在代码中尝试添加装饰器的方法未成功,需要更多信息来确定具体原因。