【问题标题】:How to reset a global variable in python "recursive" function?如何在python“递归”函数中重置全局变量?
【发布时间】:2015-04-23 09:36:30
【问题描述】:
def getValueForSpecificKey(self,capturedLog,key):

     ''' Get value from log for any specific key,caputredLog must be a string'''
     global Found
     global returnValue
     if type(capturedLog)==type({}):
         for eachKey in capturedLog:
             if eachKey==key:
                 Found=True
                 print "Found Key Match :",eachKey
                 print capturedLog[key]
                 listAppendValue=capturedLog[key]
                 #returnValue=capturedLog[key]
                 returnValue.append(listAppendValue)
                 print "="*1000
                 print "The value for key in the captured Log is -> ",capturedLog[key]
                 print " Return value "*10,(returnValue)
                 return Found,returnValue
             self.getValueForSpecificKey(capturedLog[eachKey],key)
     elif type(capturedLog) is list:
         for elements in capturedLog:
             self.getValueForSpecificKey(elements,key)
     print returnValue
     return Found,returnValue

我有这个函数,它递归迭代一个有效的 json。json 可能包含 dict 或 list。这里搜索的函数需要一些输入日志,它是 json 和一个在 json 中搜索的键。我能够迭代得到json 中的所有键。一切都很好。

但是当我尝试返回值时问题就来了。由于 returnValue 是一个全局变量。附加到列表中,继续将所有值附加到同一个列表中。即使我从一些创建类的对象其他模块并调用此函数列表仍在增长,我无法在函数调用之前/之后清除/重置returnValue。每次从外部模块创建对象时,我都需要更改作为列表的returnValue,即当第一次调用这个函数。所以我需要递归返回值是一个问题。

由于已经定义了 api,我只能更改其中的代码。

请帮忙。 谢谢。

【问题讨论】:

  • 通常你不想为这类事情使用全局变量。尝试在递归链中向上或向下传递值。
  • 另外,我不确定我是否正确理解了代码,你能准确解释一下你希望你的代码给出什么输出吗?您只想要找到的第一个结果还是所有结果?
  • 我想将 json 和 key 作为输入,并为该特定 key 提供 json 值对。有效的 json 可以有 dict 和 list。
  • 但是只有一个结果,对吧,而不是多个具有相同键的值?
  • 所有这些,如果有多个键(在嵌套 json 的情况下)在这种情况下,一个列表可能是包含该键所有值的响应。

标签: python json recursion


【解决方案1】:

好的,解决办法就到这里

在执行函数定义时评估默认参数值。这意味着在定义函数时对表达式求值一次,并且每次调用都使用相同的“预计算”值。当默认参数是可变对象(例如列表或字典)时,这一点尤其重要:如果函数修改了对象(例如,通过将项目附加到列表中),则默认值实际上已被修改。这通常不是预期的。解决这个问题的一种方法是使用 None 作为默认值,并在函数体中显式测试它,例如:

def getValueForSpecificKey(self,capturedLog,key,First=None):

     ''' Get value from requests log for any specific key,caputredLog must be a string'''
     global Found
     global returnValue
     if First is None:
         First='notnone'
         Found=False
         returnValue=[]
         print "Return Value ->",returnValue
         print "Found - >",Found

     if type(capturedLog)==type({}):
         for eachKey in capturedLog:
             print eachKey
             if eachKey==key:
                 Found=True
                 print "Found Key Match :",eachKey
                 print capturedLog[key]
                 listAppendValue=capturedLog[key]
                 returnValue.append(listAppendValue)
                 print "="*1000
                 print "The value for key in the captured Log is -> ",capturedLog[key]
                 print " Return value "*10,(returnValue)
                 return Found,returnValue
             print "CapturedLog - >",capturedLog
             print "Calling using recursion "
             self.getValueForSpecificKey(capturedLog[eachKey],key,First)
     elif type(capturedLog) is list:
         for elements in capturedLog:
             self.getValueForSpecificKey(elements,key,First)
     return Found,returnValue

【讨论】:

    【解决方案2】:
    def __init__(self):
        self.Found=False
        self.returnValue=[]
    
    def getValueForSpecificKey(self,capturedLog,key,first=[]):
        ''' Get value from requests log for any specific key,caputredLog must be a string'''
         global Found
         global returnValue
         print " FIRST --------------------------->>>>>>",first
         if not first:
             print "NOT FIRST"*1000
             time.sleep(3)
             first.append(1)
             Found=False
             returnValue=[]
         if type(capturedLog)==type({}):
             for eachKey in capturedLog:
                 if eachKey==key:
                     Found=True
                     print "Found Key Match :",eachKey
                     print capturedLog[key]
                     listAppendValue=capturedLog[key]
                     returnValue.append(listAppendValue)
                     print "="*1000
                     print "The value for key in the captured Log is -> ",capturedLog[key]
                     print " Return value "*10,(returnValue)
                     return Found,returnValue
                 self.getValueForSpecificKey(capturedLog[eachKey],key)
         elif type(capturedLog) is list:
             for elements in capturedLog:
                 self.getValueForSpecificKey(elements,key)
         return Found,returnValue
    

    我在一个类中有两个函数。我创建了 getValureForSpecificKey 的对象并传递了一个 json 和一个在其中搜索的键。我期望这个特定键的值。但是增量附加到同一个列表的键是什么即使对象不同。我不确定前一个对象是否没有被破坏?这是最不可能的,因为每个对象都具有不同的功能并且具有本地范围。

    我在这里缺少什么来使对函数的每次调用都与上一次调用分开?

    那么,我基本上想知道这个解决方案出了什么问题?

    当我只在第一次创建对象时打印值时,即使我下次创建新对象时,值也会打印为 0 第一次调用时得到的值与 1 相同,而不是 0。为什么会发生这种情况?

    【讨论】:

      【解决方案3】:

      我认为您应该将递归函数更改为不需要任何全局变量。如果你只期望找到一个结果,我认为它并不太复杂。

      def getValueForSpecificKey(self, capturedLog, key):
          '''
          Get value from log for any specific key.
          capturedLog will be searched if it is a list or dictionary.
          Returns None if the key is not found, or capturedLog is another type.
          '''
      
          if isinstance(capturedLog, dict):
              if key in capturedLog:                # base case #1 (found the key)
                  return capturedLog[key]
      
              values = capturedLog.values()
      
          elif isinstance(capturedLog, list):
              values = capturedLog
      
          else:
              return None                           # base case #2 (not a list or dict)
      
          for value in values:
              result = self.getValueForSpecificKey(value, key)      # recursive case
              if result is not None:
                  return result
      
          return None                               # nothing found in the recursive search
      

      如果您可能在不同的字典中有多个具有所需键的值,您可能需要传递一个列表:

      def getValueForSpecificKey(self, capturedLog, key, results=None):
          '''
          Get value from log for any specific key.
          capturedLog will be searched if it is a list or dictionary.
          Returns an empty list if the key is not found, or capturedLog is another type.
          '''
          if results is None:
              results = []               # start a new list if this is a non-recursive call
      
          if isinstance(capturedLog, dict):
              if key in capturedLog:
                  results.append(capturedLog[key])     # found a result, add it to the list
                  return results
      
              values = capturedLog.values()
      
          elif isinstance(capturedLog, list):
              values = capturedLog
      
          else:
              return results
      
          for value in values:  # recursive calls will add to the results list as necessary
              self.getValueForSpecificKey(value, key, results)
      
          return results
      

      【讨论】:

      • 第二个解决方案对我来说效果很好。非常感谢。我很想知道我正在研究的灵魂发生了什么。我期待@Gadi 的解决方案对我有用。
      【解决方案4】:
      def getValueForSpecificKey(self,capturedLog,key,first=[])
      global returnaValue
      if not first:
         first.append(1)
         returnaValue = []
      

      这将在您第一次调用它时创建一个全局空列表。这将表明您应该清除全局列表 returnValue。无需更改 api 并使用递归

      【讨论】:

      • 我期待它能够工作,因为它看起来在逻辑上是正确的,但不知何故它没有重置 returnaValue[] 的值。我正在从其他模块调用该函数,为该类创建对象这个函数属于。
      • 第二次为类创建对象时,first 的值附加了一个,这不应该是这种情况,因为 first 是一个局部变量。但出乎意料的是,第一个是仍然持有新对象的值。奇怪。
      猜你喜欢
      • 1970-01-01
      • 2020-10-02
      • 2012-11-06
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      相关资源
      最近更新 更多