Python 如何在没有大量手动编辑的情况下,将一个类替换为大量文件中另一个模块中的另一个类?
基本上,我有很多Python类(代表我们的数据库模式),看起来像这样:Python 如何在没有大量手动编辑的情况下,将一个类替换为大量文件中另一个模块中的另一个类?,python,automation,sed,rope,Python,Automation,Sed,Rope,基本上,我有很多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
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
的所有实例。我可以接受将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 s/a/m将是灾难性的,因为酒吧将改为bmr 如果变量名非常短和/或非唯一、不可正则, 那么也许最简单的方法就是插入
from baz import m as a
这样,您就不必再进一步修改文件中的任何其他代码
你可以用sed来改变
from foo import a,b,c
到
虽然
from foo import a,b,c
from baz import m as a
也可以,因为上次导入成功。我没有使用rope,但您不能将a移到baz,然后将baz.a重命名为baz.m。您可以在其他语言的重构工具中使用,并且建议可以
对于最小的编辑—但可能更糟糕的样式和可维护性—请使用foo。调用baz.mMonkey补丁将是一种快速而肮脏的方法—在执行任何其他导入之前,请执行以下初步操作:
import foo
import baz
foo.a = baz.m
现在,模块
foo
的属性a
的每次后续使用实际上都将根据需要使用模块baz
的类m
,而不是模块foo
的原始类a
。不是特别干净,但可能相当有效。只需确保在任何其他导入之前进行monkey修补(您也可以在对象图中查找在修补之前放置的对foo.a
的每个引用,并将其更改为baz.m
,但这更重、更复杂)。您可以尝试此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
我不会使用monkeypatching,我会实现自己的功能:
import foo
def xyz():
return foo.xyz()
def b():
return foo.b()
def c():
return foo.c()
现在我可以更改xyz()
,让它做我想做的任何事情,如果我想显式调用foo.xyz()
,我可以
此外,如果我将该代码粘贴到一个模块中,我可以在当前使用
foo
的所有模块中用从foo import
全局替换。为了简单起见,我只是使用了m
和a
。我更新了页面,使其更清晰(尽管有点俗气)。sed方法不起作用,因为我可能还会遇到类似foo import b、c、xyz的。实际上,baz代表我自己的库,foo代表第三方库。在它们之间来回移动东西是不可行的。你仍然可以进行移动-你的代码将被编辑并在调用它的代码中使用baz.a,但返回到未更改的foo,并按照Alex Martelli建议的猴子补丁在baz中实现a。不幸的是,我仍然需要在几个地方使用a。我有点犹豫要不要做更多的诡计来绕过这个问题,因为foo是一个第三方图书馆。@Jason,啊,好吧——也许你可以在需要它的地方“反转monkeypatch”foo的原始a(你可以在重新分配它之前把它藏起来)?否则,通过修改代码当然可以做到这一点,但要复杂得多(除非名称是无误的,正如您在编辑xyz而不是;-)时所指出的那样)。
import foo
def xyz():
return foo.xyz()
def b():
return foo.b()
def c():
return foo.c()