2009-11-04 27 views
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() 

本质上,我只是想用foobar替换xyz的所有实例。这是可以接受的我离开的的进口,所以这也将是罚款:

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

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

看来微不足道的做这个sed s/xyz/foobar/,但我还是不得不回去改进口声明。我在做一些手工工作时很好,但我想学习新的方法来减少它的数量。

那么你会如何做这个改变?有什么我可以用sed来做到这一点?或绳子(我没有看到任何明显的东西可以帮助我)?

回答

1

因为bar会变成bmr,所以sed s/a/m会很糟糕。

如果变量名是真正的短期和/或非唯一,非正则表达式,能, 话,或许最容易做的事情将是插入

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 

将工作太,自上次进口的胜利。

+0

其实,它们比那个更独特(并且不太可能出现在其他地方)。为了简单起见,我只是使用'm'和'a'。 – 2009-11-04 16:09:31

+0

我已经更新了页面,使它更清晰一点(虽然有点乳酪)。而sed方法不起作用,因为我可能会碰到'from foo import b,c,xyz'这样的东西。 – 2009-11-04 16:14:19

0

我没有使用绳子,但不能移动到baz然后重命名为baz.a到baz.m您可以在其他重构工具的其他语言和rope page建议它可以。

最少的编辑 - 但也许更糟糕的风格和可维护性化妆foo.a呼叫baz.m

+0

实际上,baz代表我自己的图书馆,foo代表第三方图书馆。在他们之间来回移动东西是不可行的。 – 2009-11-04 16:15:53

+0

您仍然可以这样做 - 您的代码将被编辑,并在调用它的代码中使用baz.a,但恢复到未更改的foo,并通过猴子补丁Alex Martelli建议的baz实现。 – Mark 2009-11-05 00:30:32

3

猴补丁将是快速和肮脏的方式做到这一点 - 你做任何其他进口之前,执行以下初步:

import foo 
import baz 
foo.a = baz.m 

现在,每一个后续使用模块foo的属性a的实际上是使用模块bazm类,如需要,而不是模块fooa类。不是特别干净,但可能相当有效。只要确保猴子补丁发生在任何其他导入之前(您也可以在整个对象图中追踪找到在修补前已放置到位的所有参考,并将其更改为baz.m,但这是方式较重并且麻烦)。

+0

不幸的是,我仍然需要在几个地方使用a。由于foo是第三方库,我有点犹豫要做更多的诡计来解决这个问题。 – 2009-11-04 16:19:31

+0

@Jason,很好啊 - 也许你可以在需要的地方“反转monkeypatch”foo的原始a(你可以明显地藏在一旁,然后再重新分配)。否则,它肯定可以通过修改代码来实现,但方式更复杂(除非名称无误,因为您似乎用编辑来指示xyz而不是;-)。 – 2009-11-05 01:09:56

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命令分支到一个标签(如果不是标签被给出)如果没有进行替换。在这个例子中,“从巴兹”行只追加一次:

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

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

import foo 

def xyz(): 
    return foo.xyz() 

def b(): 
    return foo.b() 

def c(): 
    return foo.c() 

现在我可以改变xyz()到让它做我想做的任何事情,如果我想要明确地致电foo.xyz(),我可以。此外,如果我将该代码粘贴到某个模块中,则可以在目前使用foo的所有模块中全局替换from foo importfrom my_foo import

相关问题