2

基本上,我有很多看起来像这样的 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。我可以接受 a 的导入,所以这也可以:

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

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

对此做一个似乎微不足道sed s/xyz/foobar/,但是我仍然必须回去更改导入语句。我可以做一些手工工作,但我想学习新的方法来减少它的数量。

那么你将如何进行这种改变呢?我可以用 sed 做些什么来做到这一点?还是绳索(我没有看到任何明显可以帮助我的东西)?

4

5 回答 5

3

Monkey-patching 将是一种快速而肮脏的方法——在你进行任何其他导入之前,执行以下初步操作:

import foo
import baz
foo.a = baz.m

现在,以后每次使用amodule的属性foo实际上都将根据需要使用mmodule的类baz,而不是原来a的 module类foo。不是特别干净,但可能非常有效。只需确保在任何其他导入之前进行猴子修补(您也可以在整个对象图中跟踪以找到foo.a在修补之前放置的每个引用并将其更改为 a baz.m但这更重且更棘手)。

于 2009-11-04T16:09:18.620 回答
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

如果没有进行替换,则 in 中的T命令sed分支到标签(如果没有给出标签,则跳转到结尾)。在此示例中,“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
于 2009-11-04T20:29:17.753 回答
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

也可以,因为最后一次导入获胜。

于 2009-11-04T16:07:24.753 回答
0

我不会使用monkeypatching,我会实现自己的功能:

import foo

def xyz():
    return foo.xyz()

def b():
    return foo.b()

def c():
    return foo.c()

现在我可以改变xyz()让它做任何我想做的事情,如果我想明确地调用foo.xyz(),我可以。

此外,如果我将该代码粘贴在一个模块中,我可以在当前使用的所有模块中全局替换from foo import为.from my_foo importfoo

于 2009-11-05T15:32:35.667 回答
0

我没有使用rope,但你不能将a 移动到baz 然后将baz.a 重命名为baz.m 你可以在其他语言的其他重构工具中使用rope 页面建议它可以。

对于最少的编辑 - 但可能更糟糕的风格和可维护性使 foo.a 调用 baz.m

于 2009-11-04T16:08:22.870 回答