2012-08-07 19 views
5

Jeśli utworzyć funkcję pyton dekorator jak tenparametry przejścia do dekorator przy starcie

def retry_until_true(tries, delay=60): 
    """ 
    Decorator to rety a function or method until it returns True. 
    """ 
    def deco_retry(f): 
     def f_retry(*args, **kwargs): 
      mtries = tries 
      rv = f(*args, **kwargs) 
      while mtries > 0: 
       if rv is True: 
        return True 
       mtries -= 1 
       time.sleep(delay) 
       rv = f(*args, **kwargs) 
      return False 
     return f_retry 
    return deco_retry 

można go używać jak to

@retry_until_true(20, delay=30) 
    def check_something_function(x, y): 
     ... 
     return True 

Ale czy istnieje sposób przekazać różne wartości dla „próbach "i" opóźnienie "do dekoratora w czasie pracy, więc 20 i 30 to zmienne?

+2

Dekorator jest wywoływany w czasie def. Jeśli chcesz przekazać różne wartości w czasie wykonywania, dlaczego nie masz po prostu funkcji. Np .: 'def retry_until_true (func, próbuje, opóźnienie): ...'. –

Odpowiedz

3

Można użyć klasy jako dekorator, ze zmiennych instancji dla tries i delay:

class RetryUntilTrue(object): 
    def __init__(self, f=None, tries=10, delay=30): 
     self.f = f 
     self.tries = tries 
     self.delay = delay 

    def __call__(self, *args, **kwargs): 
     if self.f is None: 
      self.f = args[0] 
     else: 
      tries = self.tries 
      while tries: 
       if self.f(*args, **kwargs): 
        return True 

       tries -= 1 
       time.sleep(self.delay) 

Zastosowanie:

@RetryUntilTrue 
def foo(x): 
    pass 

foo.tries = 20 
foo.delay = 1 

@RetryUntilTrue(tries=100, delay=9999) 
def bar(x): 
    pass 

bar.tries -= 1 
bar.delay = foo.delay 
1

Pewnie można, tylko gniazdo definicja swoją funkcję w innej funkcji, na przykład:

def explicit_setup_func(tries, delay=60): 
    @retry_until_true(tries, delay) 
    def check_something_function(x, y): 
     # Code 

Jednak klauzula ss dekorator rozwiązanie jest bardziej praktyczne.

Powiązane problemy