2017-09-01 1 views
0

Handhabung ein NameError Referenzierung hebt ein SyntaxError:

Ich mache eine Dekorateur Funktion also, die einen Generator-Funktion zu einem Wörterbuch verbindet, mit der Absicht, die send() Funktion weniger umständlich zu machen zu machen.`NameError` Handhabung ohne` SyntaxError` zu erhöhen, wenn globale Variablen in python3

Das Standardverhalten ist ein Wörterbuch verwenden namens global_registry_dict definiert in (Überraschung!) Den globalen Namensraum. Wenn global_registry_dict nicht existiert und ein alternatives Wörterbuch nicht explizit übergeben wird, wird NameError von Python ausgelöst.

Wenn ich versuche, den Fehler durch Erstellen der Variablen im globalen Namespace zu behandeln, bekomme ich eine SyntaxError sagt mir, dass die Variable vor der Zuweisung referenziert wird. Das macht Sinn ... aber ... wie ... das versuche ich zu beheben!

Jede Hilfe würde sehr geschätzt werden!

Quelle für den Ausstatter:

def make_stateless_actor(func): 
    def wrapper(registry_dict=None, *args, **kwargs): 
     try: 
      if registry_dict is None: 
       internal_registry_dict = global_registry_dict 
      elif isinstance(registry_dict, dict) or issubclass(registry_dict, dict): 
       internal_registry_dict = registry_dict 
      else: 
       internal_registry_dict = global_registry_dict 
     except NameError: # <<== CATCHES IF `global_registry_dict` IS REF'D BUT NOT DEFINED. 
      global global_registry_dict # <<== SYNTAX ERROR HAPPENS HERE 
      global_registry_dict = {} 
      internal_registry_dict = global_registry_dict 
     gen = func(*args, **kwargs) 
     next(gen) 
     internal_registry_dict[func.__name__] = gen 
    return wrapper 

Ausnahme zurückgegeben:

File "C:/yall/dont/need/to/know/this/generator_pipeline_utils.py", line 74 
global global_registry_dict 
^ 
SyntaxError: name 'global_registry_dict' is used prior to global declaration 

Quelle des gesamten Moduls:

# global_registry_dict = {} 


def make_stateless_actor(func): 
    """ 
    DESCRIPTION: 
    =========== 
    This DECORATOR FUNCTION simplifies & centralizes the use of `send()` on generators. 

    It does this by ASSOCIATING the decorated function to a dictionary: 

     - by default, a global variable named `global_registry_dict` will be used. 
     - by default, `global_registry_dict = {}` will be created in the GLOBAL-NAMESPACE if it does not exist. 

    IMPORTANT NOTE: 
    ============== 
    Use the `registry_dict` kwarg to manually assign your generator-func to an alternate dictionary: 
      `foo_decorated_func(registry_dict=foo_alternative_dictionary)` 

    REQUIREMENTS: 
    ============ 
    You can apply `@make_stateless_actor` to any GENERATOR FUNCTION which: 

     - INCLUDES A `yield` expression to the RIGHT of an `=` sign. 
     - INCLUDES `**kwargs` as a function argument. 
    """ 
    def wrapper(registry_dict=None, *args, **kwargs): 
     try: 
      if registry_dict is None: # <<-- necessary to prevent the next elif from throwing an exception. 
       internal_registry_dict = global_registry_dict 
      elif isinstance(registry_dict, dict) or issubclass(registry_dict, dict): 
       internal_registry_dict = registry_dict 
      else: 
       internal_registry_dict = global_registry_dict 
     except NameError: 
      print('WARNING: global_registry_dict IS NOT DEFINED AND YOU DID NOT EXPLICITLY PASS registry_dict TO THE DECORATED FUNCTION.\n\ 
        `global_registry_dict = {}` has been instantiated in the global-namespace.\n') 
      global global_registry_dict 
      global_registry_dict = {} 
      internal_registry_dict = global_registry_dict 
     gen = func(*args, **kwargs) 
     next(gen) 
     internal_registry_dict[func.__name__] = gen 
    return wrapper 

@make_stateless_actor 
def printer(*args, **kwargs): 
    while True: 
     item = yield 
     print("Got: ", item) 

def send(name, msg, registry_dict=None): 
    if registry_dict is None: 
     global_registry_dict[name].send(msg) 
    else: 
     registry_dict[name].send(msg) 

if __name__ == "__main__": 
    printer(registry_dict=None) #<<==BEGIN THE CRAZY. 
    # send('printer', 'HEY WHAT IS UP?') 
    # send('printer', 666) 
    # send('printer', [1, 'a', [], True]) 

Antwort

1

Sie den Namen verwenden global_registry_dict in der else Klausel ein Paar aufreihen. Wenn es global sein soll, müssen Sie es vor der Verwendung so deklarieren, wie es in der Fehlermeldung steht. Im Allgemeinen werden Namen am Anfang der Funktion als global deklariert.

+0

Ich kann einen Scheck am Anfang hinzufügen, aber ich denke, ich soll geklärt werden: Gibt es keine Möglichkeit, eine globale Variable nach der Verwendung von 'except' zu instanziiert, um herauszufinden, dass es noch nicht existiert? –

+0

Ja. Tun Sie, was Sie tun, außer, verschieben Sie die 'globale' Deklaration über die erste Verwendung des Namens, wie ich gerade gesagt habe. – kindall

+0

Lol. ja. Vielen Dank. –