2009-11-04 4 views
2

는,이 같은 것을 보면 (우리의 데이터베이스 스키마를 나타냄) 파이썬 클래스 많은 있습니다수작업으로 많은 편집 작업을하지 않고도 많은 수의 파일로 다른 모듈의 다른 클래스로 클래스를 대체하려면 어떻게해야합니까? 기본적으로

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로 할 수있는 일이 있습니까? 또는 밧줄 (나는 여기에서 나를 도와 줄 명백한 아무것도 보지 못한다)?

답변

1

sed s/a/m은 막대가 bmr로 변경되므로 재앙이됩니다. 그런 다음에이없는

변수 이름이 수 비 정규식-, 정말 짧은 및/또는 고유하지 않은 경우, 할 아마도 가장 쉬운 것은

from baz import m as a 

를 삽입하는 것입니다 다른 코드를 파일에서 더 아래로 변경하십시오.

당신은

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

마지막 수입 승리 이후, 너무 일 것이다

from foo import a,b,c 

from foo import b,c 

불구하고 변경 나오지도 사용할 수 있습니다.

+0

사실, 그보다 더 독특합니다 (다른 곳에서는보기 힘들 것입니다). 단순함을 위해서'm'과'a'를 사용했습니다. –

+0

페이지가 조금 더 명확 해 지도록 업데이트했습니다 (다소 치즈가 많았지 만). 그리고 sed 메소드는'foo import b, c, xyz' 같은 것들을 실행할 수도 있기 때문에 작동하지 않을 것입니다. –

0

나는 로프를 사용하지 않았지만 a를 baz로 이동 한 다음 baz.a를 baz.m으로 바꿀 수는 없습니다. 다른 언어의 다른 리팩토링 도구에서는 rope page이 그렇게 할 수 있음을 나타냅니다. 최소한의 편집에 대한

- 그러나 아마 더 스타일 및 유지 메이크 foo.a 호출 baz.m

+0

사실, baz는 제 자신의 라이브러리를 나타내며 foo는 타사 라이브러리를 나타냅니다. 그들 사이에 물건을 앞뒤로 움직이는 것은 불가능합니다. –

+0

당신은 여전히 ​​이동을 할 수 있습니다 - 당신의 코드는 편집되고 코드를 호출하는 코드에서 baz.a를 사용하지만 변경되지 않은 foo로 돌아가고 Alex Martelli가 제안한 원숭이 패치에 의해 baz에서 구현을합니다. – Mark

3

원숭이 패치는 작업을 수행 할 신속하고 더러운 방법이 될 것이다 - 당신은 다른 가져 오기를 수행하기 전에 수행 예비 다음 오히려 모듈 foo의 원래 클래스 a보다, 필요에 따라

import foo 
import baz 
foo.a = baz.m 

지금, 모듈 foo의 속성 a 이후의 모든 사용은 실제로 모듈 baz의 클래스 m을 사용하는 것입니다. 특히 깨끗하지는 않지만 잠재적으로 매우 효과적입니다.다른 수입이 있기 전에 원숭이 패칭이 발생했는지 확인하십시오. (패치를 적용하기 전에 foo.a에 대한 모든 참조를 찾아서 baz.m으로 바꿀 수 있지만, 방법은입니다. 더 까다로운). 동등하게,

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

나 :

+0

불행히도, 나는 아직도 몇 곳에서 a를 사용해야합니다. foo가 제 3 자 라이브러리 인 것처럼이 문제를 해결하기 위해 더 많은 속임수를 쓰는 것을 주저합니다. –

+0

@Jason, 아 - ​​어쩌면 당신은 "역전환"을 할 수있는 몇 곳에서 foo의 원본 A (재 지정하기 전에 분명히 숨겨 둘 수 있습니다)? 그렇지 않으면 확실히 코드를 변경하여 수행 할 수 있지만, (이름이 틀림없는 경우가 아니라면, 편집 대신에 ;-) 대신 xyz를 사용하는 것으로 나타납니다. –

1

sed 스크립트를 시도 할 수 있습니다

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를 사용하지 것이다 : 지금은에 xyz()을 변경할 수 있습니다

import foo 

def xyz(): 
    return foo.xyz() 

def b(): 
    return foo.b() 

def c(): 
    return foo.c() 

을 내가 원하는 모든 것을하도록하십시오. 그리고 내가 명시 적으로 foo.xyz()에 전화하고 싶다면, 할 수 있습니다.

또한 해당 코드를 모듈에 고정하면 현재 foo을 사용하는 모든 모듈에서 from foo importfrom my_foo import으로 대체 할 수 있습니다.