处理`NameError`没有python3引用全局变量时

问题描述:

处理一个NameError是提高养`SyntaxError`一个SyntaxError

所以我做这一个发电机功能的字典相关联的装饰功能,与意图使send()功能使用起来不那么麻烦。处理`NameError`没有python3引用全局变量时

默认行为是使用名为global_registry_dict的字典(惊喜!)中定义的全局名称空间。

如果global_registry_dict不存在,并且替代字典没有明确传入,NameError由python引发。

当我尝试通过在全局命名空间中创建变量来处理错误时,我得到一个SyntaxError告诉我该变量在赋值之前被引用。这是有道理的......但是......就像......这就是我想要解决的问题!

任何帮助将不胜感激!

来源为装饰:

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 

异常返回:

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 

整个模块的来源:

# 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]) 

您的else条款一对情侣在使用的名称global_registry_dict排队。如果它是全球性的,在使用它之前必须声明它,就像错误信息所说的那样。一般而言,名称在函数的开始处声明为全局名称。

+0

我可以在开头添加一个检查,但我想我应该澄清一下:在使用'except'发现它不存在之后,是否没有办法实例化全局变量? –

+0

是的。做你正在做的事情,除了像第一次使用名称那样移动'global'声明,就像我刚才所说的那样。 – kindall

+0

大声笑。是的。谢谢。 –