【问题标题】:How can I access variables defined within if/elif statements at the end of the parent python function?如何访问在父 python 函数末尾的 if/elif 语句中定义的变量?
【发布时间】:2017-07-12 18:10:04
【问题描述】:

如何在父 python (3.6) 函数中进一步引用 if/elif 语句中定义的变量?

例如,下面是我的代码的模型 - 我正在尝试在下面每个“if”和“elif”块中定义的变量“打印”或“使用”,在函数的末尾包含在其中定义变量的 if/elif 语句,但是当我运行代码时,我在 pycharm 中得到一个未解决的引用错误和以下 python 错误:

    UnboundLocalError: local variable 'a1_summary' referenced before assignment

我对 python 和编码比较陌生,不明白我哪里出错了,因为我期望变量是在同一个函数中定义的,所以它们应该对打印语句末尾的 print 语句“可见”函数...

这种情况应该使用全局变量吗?

def Process_Data(incoming_data):

      if incoming_data.count(',') == 2:
         data_summary = incoming_data.split(',')
         a1_summary, b1_summary = data_summary[0], data_summary[1]

      elif incoming_body.count(',') == 3:
           data_summary = incoming_data.split(',')
           a2_summary, b2_summary, c2_summary = data_summary[0], data_summary[1], data_summary[2]

      print(a1_summary, b1_summary, a2_summary, b2_summary, c2_summary )

      else:
           pass

非常感谢任何帮助或建议 - 谢谢。

更新到上述内容

我试图保持问题简单,但可能会混淆一些事情,因为我试图在处理来自 rabbitmq 消息队列的消息的函数中使用 if/elif 语句 - 我需要根据逗号的数量来处理消息在相应的消息中并将消息的部分分配给变量,然后将 if/elif 语句接收和处理的每条消息的部分聚合到一个数组中,以便稍后我可以将其传递给程序中的另一个函数。

我认为每次函数接收到与 if 或 elif 语句匹配的传入数据时,我可能会出错 - 任何与其他条件匹配的先前或新数据仍将作为变量保存在函数中,例如我在想该函数包含来自 if/elif 块的变量,并且只更新相应逻辑语句处理的任何新数据...

【问题讨论】:

  • 用默认值在 if 之外定义它们,然后在 if 中重新分配它们。
  • 谢谢,但我已经尝试在函数的开头定义 a1_summary = '' 和 b1_summary = '' 但是当 if/elif 语句进行处理时,这些值似乎没有得到更新 - print 语句只“打印”两个空格,然后是 a2_summary、b2_summary、c2_summary 的值。对不起,如果我在这里很厚,但你能指点一下吗?
  • 只有其中一个语句会执行,因此您将拥有 a1 和 b1 或 a2、b2 和 c2。根据缩进,你的“else”语句也应该抛出错误。
  • @mauve - 谢谢 - 我想我知道哪里出错了 - 我在想这个函数会保存每个逻辑块中定义的变量的值,然后我可以在函数的结尾......我应该使用全局变量来保存这些变量作为一种解决方法 - 从我读过的内容来看,人们强烈建议不要使用 GV......

标签: python variables if-statement scope global-variables


【解决方案1】:

您的代码的问题是 a1_summaryb1_summary 只有在您的传入数据包含两个逗号时才被定义,在这种情况下, a2_summaryb2_summaryc2_summary 永远不会被定义。

在输入中出现 3 个逗号时出现相反的问题 - 如果逗号少于 2 个或多于 3 个,则两者都出现。

因此,无论您的输入是什么,您的某些变量永远不会被定义。

这里绝对没有范围问题。如果您想了解有关 Python 3 中作用域的更多信息,可以查看this answer

为了解决您的问题,您可以在函数开头为这些变量指定默认值。这可能是一个空字符串,例如

a1_summary = b1_summary = a2_summary = b2_summary = c2_summary = ''

然后,无论您的代码采用何种路径,所有变量都将在某个时候定义。

【讨论】:

    【解决方案2】:

    查看您的代码,我认为您正在尝试做的事情可以更有效地完成,并修复您的错误。看起来您正试图用逗号分割输入,然后打印每个元素。您可以将它们放在一个列表中,然后打印该列表,而不是做您现在正在做的事情。我认为这会做你想要的

    def Process_Data(incoming_data):
        print(*incoming_data.split(","))
    

    我不太确定你为什么要这样做,因为它实际上不会做任何事情,除了用空格替换逗号。如果要返回带有结果的元组,请将打印替换为

        return(tuple(incoming_data.split(",")))
    

    你也可以把它变成一个 lambda:

    Process_data = lambda incoming_data: print(*incoming_data.split(","))
    

    Process_data = lambda incoming_data: return(tuple(incoming_data.split(",")))
    

    如果你想根据数字改变变量的类型,那绝对可以做到。

    def Process_Data(incoming_data):
        data_input = incoming_data.split(",")
        if len(data_input) == 3:
             dataA, dataB, dataC = int(data_input[0]), str(data_input[1]), int(data_table[2])
        elif len(data_input) == 2:
             dataA, dataB, dataC = str(data_input[0]), int(data_input[1]), None
        return(dataA, dataB, dataC)
    

    您可以根据需要更改所需输出的类型。这与您所做的非常相似,只是更短一些,并将剩余的数据点定义为 None。

    【讨论】:

    • 谢谢 Sam,对不起,我没有说得更清楚,但我正在尝试从队列中接收两条消息,根据逗号的数量将消息的内容拆分为变量- 其中一些是字符串,其中一些是数字 - 然后我想聚合这些变量,以便我可以将它们传递给另一个函数以进一步进行计算 - 抱歉,我没有说得更清楚 - 我试图简化问题,但可能有混淆的东西..
    【解决方案3】:

    如果这个代码:

    def Process_Data(incoming_data):
    
          if incoming_data.count(',') == 2:
             data_summary = incoming_data.split(',')
             a1_summary, b1_summary = data_summary[0], data_summary[1]
    
          elif incoming_body.count(',') == 3:
               data_summary = incoming_data.split(',')
               a2_summary, b2_summary, c2_summary = data_summary[0], data_summary[1], data_summary[2]
    
          print(a1_summary, b1_summary, a2_summary, b2_summary, c2_summary )
    

    导致此错误:

    UnboundLocalError: local variable 'a1_summary' referenced before assignment
    

    这只能是因为当您尝试在print 语句中使用a1_summary 时,它没有被赋值。

    您分配给a1_summary 的唯一位置是在此块中:

    if incoming_data.count(',') == 2:
         data_summary = incoming_data.split(',')
         a1_summary, b1_summary = data_summary[0], data_summary[1]
         ^^^^^^^^^^
    

    所以这段代码没有被执行,也就是说incoming_data.count(',')不等于2

    这也是在函数顶部初始化 a1_summary = "" 等时“值似乎没有更新”的原因。

    如果你想让函数记住以前的值,你应该使用一个类来代替,例如

    class DataProcessor(object):
        def __init__(self):
            self.a1 = self.a2 = self.b1 = self.b2 = self.c2 = ""
    
        def process(incoming_data):
            comma_count = incoming_data.count(',')
            if comma_count == 2:
                self.a1, self.b1 = data_summary[0], data_summary[1]
            elif comma_count == 3:
                self.a2, self.b2, self.c2 = ... you get the point...
            else:
                pass  # or log if it's an error condition
            self.print_summary()
    
        def print_summary(self):
            print(self.a1, self.b1, self.a2, self.b2, self.c2)
    

    用法:

    dp = DataProcessor()
    ...
    dp.process(data)
    

    如果你不想改变你的API,你可以调用process方法__call__代替,然后将其用作:

    Process_Data = DataProcessor()  # keep original function name
    ...
    Process_Data(data)  # calls DataProcessor.__call_
    

    【讨论】:

    • 谢谢你thebjorn - 我会测试你写的东西然后回来找你。
    • 感谢您抽出宝贵时间发布 thebjorn - 我是编码/python 新手,并尝试在我的项目中使用您的建议,但我缺乏理解,因此无法根据需要使其工作 - 我发现我在 config.py 文件中定义变量,然后根据需要在我的函数中导入和引用这些变量 - 这似乎已经奏效,因为我现在可以做我需要做的事情 - 我不怀疑你建议的是一种更好/更高级的方法,但以我目前的理解水平,它对我不起作用......我会努力改变它!
    【解决方案4】:

    感谢所有对我的问题发表评论的人,您让我深思熟虑,但是我似乎找到了解决问题的方法/解决方案如下:

    我创建了一个 config.py 文件并在其中定义了变量,例如

    config.py
    
    a1_summary = ""
    b1_summary = ""
    
    a2_summary = ""
    b2_summary = ""
    c2_summary = ""
    

    然后在我的“主”python 脚本文件中,我导入了“config”并使用前缀“config”引用了它包含的变量。在我的函数中 - 我原始示例中的更新代码如下所示:

    import config
    ...
    
    def Process_Data(incoming_data):
    
      if incoming_data.count(',') == 2:
         data_summary = incoming_data.split(',')
         config.a1_summary, config.b1_summary = config.data_summary[0], config.data_summary[1]
    
      elif incoming_body.count(',') == 3:
           data_summary = incoming_data.split(',')
           config.a2_summary, config.b2_summary, config.c2_summary = config.data_summary[0], config.data_summary[1], config.data_summary[2]
    
      print(config.a1_summary, config.b1_summary, config.a2_summary, config.b2_summary, config.c2_summary )
    
      else:
           pass
    

    现在,我可以将每个 if/elif 语句的值聚合到代码底部的 print 语句中。

    我认为使用上面 thebjorn 建议的类可能是这样做的首选方式,但是由于我是 python/编码的新手,目前这有点超出我的理解,上面的解决方案允许我做我需要的事情暂时去。

    我意识到我需要更多地了解类并打算这样做,因为我认为使用这些会更优雅,并且不需要外部 config.py 文件。

    我希望这可能对那些目前与我处于相似位置的人有用。

    【讨论】:

    • 谢谢,经过一番搜索,这是对我来说需要最少代码更改的解决方案。
    【解决方案5】:

    由于作用域,您必须在 if/elif 块之外定义它们,然后在内部重新定义它们。

    【讨论】:

    • 不是范围问题。这里唯一的作用域是函数,缩进块(iffor...)创建作用域。
    猜你喜欢
    • 1970-01-01
    • 2021-03-10
    • 2022-08-19
    • 2022-11-23
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多