2009-07-06 4 views
4

내가 예로 바로 갈 것 한 번 경우에도보다 더 이상 실행되도록 표시 없습니다 :실내 장식은 메소드가 호출 여러 번

class Foo: 
    @execonce 
    def initialize(self): 
    print 'Called' 

>>> f1 = Foo() 
>>> f1.initialize() 
Called 
>>> f1.initialize() 
>>> f2 = Foo() 
>>> f2.initialize() 
Called 
>>> f2.initialize() 
>>> 

내가 execonce을 정의하기 위해 노력하지만 방식에서 하나를 쓸 수 없습니다.

PS : 나는 initialize에 대한 __init__의 코드를 정의 할 수 없습니다 객체가 초기화 언젠가 후 를 호출 할 수있다.

class Foo: 
    def __init__(self): 
    self.initialize_called = False 
    def initialize(self): 
    if self.initalize_called: 
     return 
    self.initialize_called = True 
    print 'Called' 

이 간단하고 읽기 쉬운 : - CF는 cmdln issue 13

+1

측면 설명 : 두 번째 호출을 무시하지 않는 것이 좋습니다. 대신 예외를 발생시켜야합니다. 호출자가 두 번 초기화하는 경우 잘못된 것이 발생하고이를 자동으로 무시하지 않고보고해야합니다. 물론, 나는 당신의 구체적인 문제를 모른다. –

+0

스테파노, 나는 동의한다. 이것은 나에게 이상하다고 느낀다. 기본적으로, 테스트 케이스는''svn commit ''과 같이''command.do_commit'과''command.do_update'와 같이이 서브 커맨드 메소드를 순차적으로 호출합니다. 그리고이 각각의 서브 커맨드는'initialize' 메소드를 호출해야합니다 (cmdln issue 13 참조). 나는 예외를 발생시키고 싶지 않다. 왜 호출자 (테스트 케이스)는 그런 내부 세부 사항을 알아야 할까? –

답변

6
import functools 

def execonce(f): 

    @functools.wraps(f) 
    def donothing(*a, **k): 
     pass 

    @functools.wraps(f) 
    def doit(self, *a, **k): 
     try: 
      return f(self, *a, **k) 
     finally: 
      setattr(self, f.__name__, donothing) 

    return doit 
+0

'TypeError : donothing()은 최소한 하나의 인자 (0이 주어진다)' –

+0

을 얻습니다.'self' 인자를'donothing' 메소드에서 제거합니다.이 작업을 할 수있었습니다. –

+2

doct와 donothing에 functools.wraps decorator를 추가하는 것이 좋습니다. 이 방법은 문서 및 함수의 다른 속성이 동일합니다. –

0

당신이 뭔가를 할 수 있습니다. __init__ 함수에는 다른 인스턴스 변수와 일부 코드가 필요하지만 사용자의 요구 사항을 충족시킵니다.

+0

저는 코드에서 모든 클래스에 대해 이것을하는 것을 피하고 싶습니다. DRY 원칙의 이점을 위해 데코레이터 또는 무언가를 선호합니다. –

0

def foo(): 
    try: 
      foo.called 
    except: 
      print "called" 
      foo.called = True 

방법과 유사한 무언가를 시도하고 기능 개체입니다. 메소드와 속성을 추가 할 수 있습니다. 이것은 귀하의 경우에 유용 할 수 있습니다. 데코레이터를 원한다면 데코레이터가 메소드를 할당하도록하십시오. 그러나 먼저 플래그를 확인하십시오. 플래그가 발견되면 null 메소드가 리턴되어 결과적으로 실행됩니다.

+0

데코레이터가 호출 된 메소드가 아직 객체에 묶여 있지 않기 때문에 작동하지 않을 수 있으며'initialize'는 모든 객체가 아닌 * 각 객체에 대해 * 호출됩니다. –

+0

흠. 너는 요점이있다. –

관련 문제