重写python脚本,在每个脚本中注入一个方法';s类

重写python脚本,在每个脚本中注入一个方法';s类,python,code-generation,Python,Code Generation,假设我有一个python模块foo.py,它包含: class Foo(object): def __init__(self): pass 接下来,我想解析这个脚本,并在它的每个类中注入一个方法,将其重新写入如下内容: class Foo(object): def __init__(self): pass def my_method(self): pass # do some stuff here 我注意到Python2

假设我有一个python模块foo.py,它包含:

class Foo(object):
    def __init__(self):
        pass
接下来,我想解析这个脚本,并在它的每个类中注入一个方法,将其重新写入如下内容:

class Foo(object):
    def __init__(self):
        pass
    def my_method(self):
        pass # do some stuff here

我注意到Python2.6有一个
ast
模块可以用于此,但不幸的是,我需要在Python2.5中这样做。欢迎您提出任何建议。

您已经有脚本了吗?你现在应该可以用猴子修补它了。为了满足您当前的需求,可以采用以下方式:

class Foo(object):
    def my_method(self):
        pass
或者,您可以定义
my method
,并将其作为属性添加到
Foo
类中:

def my_method(self):
    pass

Foo.my_method = my_method
#or
Foo.__dict__.my_method = my_method
解决办法是:

class Foo(object):
    def __init__(self):
        pass

import new

def some_func(self):
    print "foobar"

Foo.my_method = new.instancemethod(some_func, None, Foo)
问题是,我不喜欢在文件末尾附加新的方法定义。我希望生成的脚本中的类如下所示:

class Foo(object):
    def __init__(self):
        pass
    def my_method(self):
        print "foobar"

但是,如果不构建、修改并写回sintax树,就无法找到解决方案。

我理解您的意图,但是如果您的源代码相当简单,那么您可以完全跳过整个解析和写回,只运行一个regexp

比如:

re.sub('^class\s+(\w+):\s*\n', 'class \\1:\n%s' % method_source, file_source, flags=re.M)

只需正确缩进即可。

您是在解析.py Python源文本文件并想要写出.py文件,还是在谈论修改运行时内存中的类定义?@dkamins解析.py Python源文本文件并想要写出.py文件我想他想在运行时动态添加它们,并且不指定每个类名。类似于foo.classes中垃圾邮件的
:spam.my_method=my_method
。我考虑了第二种方法。它不会像您的示例那样直接工作,但它可以通过使用python的新模块()来工作。问题是,生成的脚本很难阅读,所以我更喜欢你的第一个建议,但我不知道如何安全地做到这一点,而不依赖于构建语法树,向其添加节点,然后重写它…@Ioan你应该为你的问题添加答案,并允许其他人投票支持它。这听起来是一种明智的方法。@Ioan如果重写整个语法树,可能会丢失注释(不包括在标准Python解析器中)和格式。@Gurgeh是的,我并不在乎丢失注释。我唯一关心的是输出脚本是否能在预期模式下运行。这里的示例只是为了指出我正在尝试完成的事情。我试图编辑的实际源代码是一个复杂得多的脚本,因此我不会依赖纯字符串解析。例如,通过查看您的正则表达式,我可以将单词“class”作为多行注释的一部分,在这种情况下,正则表达式将失败。它失败的方式确实不多。嵌套类不会被修补。有吗?应该修补吗?如果类周围有多行注释,那么该类也会被编辑。如果你想要一个真正的解析器,你可以使用pyparsing和这个语法定义:正则表达式不适用于新样式的类。即使修复了它,也可能会出现继承类跨多行分布的情况。您也可以解决这个问题,但是,这样一来,生成的正则表达式就有可能成为一个怪物。