如何在多个文件中不进行大量手动编辑,替换一个类为另一个模块中的类?

2 投票
5 回答
1251 浏览
提问于 2025-04-15 15:39

基本上,我有很多Python类(这些类代表我们的数据库结构),它们看起来像这样:

from foo import xyz, b, c

class bar(object):
    x = xyz()
    y = b()
    z = c()

...我想把它们改成这样:

from foo import b, c
from baz import foobar

class bar(object):
    x = foobar()
    y = b()
    z = c()

简单来说,我就是想把所有的xyz替换成foobar。我觉得保留一个导入语句是可以的,所以这样也没问题:

from foo import a, b, c
from baz import foobar

class bar(object):
    x = foobar()
    y = b()
    z = c()

sed s/xyz/foobar/来做这个看起来很简单,但我还得回去改导入语句。我可以接受做一些手动的工作,但我想学习一些新方法来减少这些工作量。

那么,你会怎么做这个更改呢?我能用sed做些什么吗?或者用rope(我没有看到有什么明显的办法可以帮我)?

5 个回答

1

你可以试试这个 sed 脚本:

sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'

或者,等效的写法是:

sed 's/\(^from foo import.*\)\(xyz, \|, xyz\)\(.*\)/\1\3/; T; a\from baz import foobar'

如果你这样尝试,就会得到下面的结果:

$ echo "from foo import xyz, b, c"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar

$ echo "from foo import b, xyz, c"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar

$ echo "from foo import b, c, xyz"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar

sed 中,T 命令会在没有进行替换时跳转到一个标签(如果没有标签,就跳到最后)。在这个例子中,“from baz”这一行只会被添加一次:

$ echo "from foo import d, e, f
from foo import xyz, b, c
from bar import g, h, i"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/;a\from baz import foobar'
from foo import d, e, f
from foo import b, c
from baz import foobar
from bar import g, h, i
1

用命令 `sed s/a/m` 来替换的话会很糟糕,因为这样会把 "bar" 变成 "bmr"。

如果变量名真的很短,或者不太独特,无法用正则表达式处理,那么最简单的方法可能就是插入

from baz import m as a

这样你就不需要去修改文件中其他地方的代码了。

你可以用 `sed` 来把

from foo import a,b,c 

改成

from foo import b,c

不过

from foo import a,b,c 
from baz import m as a

也可以这样做,因为最后导入的会覆盖之前的。

3

猴子补丁是一种快速但不太干净的方法。在你进行其他导入之前,先执行以下准备工作:

import foo
import baz
foo.a = baz.m

这样一来,之后每次使用模块 foo 的属性 a 时,实际上会使用模块 baz 的类 m,而不是模块 foo 的原始类 a。虽然这种方法不太优雅,但可能会非常有效。一定要确保猴子补丁是在其他导入之前进行的(你也可以遍历整个对象图,找到所有在补丁之前引用的 foo.a,然后把它们改成 baz.m,但这会复杂得多,也更麻烦)。

撰写回答