代码之家  ›  专栏  ›  技术社区  ›  nicolas

python中变量的直接捕获[复制]

  •  0
  • nicolas  · 技术社区  · 4 年前

    出于某种原因,要捕获变量,比如 i 这里需要定义一个函数,然后调用它 捕获 并且,在调用时,使用3,即用于 .

    是否有更好的方法来捕获变量?(没有像那些函数定义/调用那样多余的语法噪音)

    class Node(object):
        def __init__(self, value, next=None):
            self.value = value
            self.next = next
        
        def __str__(self):
            return str(self.value) + ',' + str(self.next)
        
        def list2LinkedListFoldrImpPb(nums):
          ret = {0:lambda x:x}
          i = 0  
          for num in nums:
            ret[i+1] = lambda rs: ret[i](Node(num, rs))#---- i NOT captured !!
            i = i+1
          return ret[i](None)
        
        def list2LinkedListFoldrImp(nums):
          ret = {0:lambda x:x}
          i = 0
          def setf(ret, i, num):
              ret[i+1] = lambda rs: ret[i](Node(num, rs))
          for num in nums:
            setf(ret, i, num) #---- i captured !!
            i = i+1
          return ret[i](None)
        
        
        print(list2LinkedListFoldrImpPb([5,4,1])) # maximum recursion depth exceeded  !!!
        print(list2LinkedListFoldrImp([5,4,1])) # works 
    

    解决方案

    作为参考,正如重复链接中提到的那样,解决方案是确保列出所有要作为本地参数捕获的变量。

    捕获体内,创建范围/环境(闭包的一部分) 只有 调用函数时(和默认值 论据 -我想这是通话的一部分- 捕获)

    class Node(object):
      def __init__(self, value, next=None):
        self.value = value
        self.next = next
    
      def __str__(self):
        return str(self.value) + ',' + str(self.next)
    
    # Creating a function and calling it works
    def list2LinkedListFoldrOK(nums):
      ret = {0:lambda x:x}
      i = 0
      def setf(ret, i, num):
          ret[i+1] = lambda rs: ret[i](Node(num, rs))
      for num in nums:
        setf(ret, i, num)
        i = i+1
      return ret[i](None)
    
    #Pb : The i in each lambdas refers to the *last* value that i had in the scope it came from, i.e., 3
    def list2LinkedListFoldrImpKO(nums):
      ret = {0:lambda x:x}
      i = 0  
      for num in nums:
        ret[i+1] = lambda rs: ret[i](Node(num, rs))
        i = i+1
      return ret[i](None)
    
    #Solution : List all captured variables as locals via default
    def list2LinkedListFoldrImpOK2(nums):
      ret = {0:lambda x:x}
      i = 0  
      for num in nums:
        ret[i+1] = lambda rs, i=i, num=num: ret[i](Node(num, rs))
        i = i+1
      return ret[i](None)
    
    #Solution : or make an actual call 
    def list2LinkedListFoldrImpOK3(nums):
      ret = {0:lambda x:x}
      i = 0  
      for num in nums:
        ret[i+1] = (lambda i,num: lambda rs: ret[i](Node(num, rs)))(i,num)
        i = i+1
      return ret[i](None)
    
    
    
    print(list2LinkedListFoldrImpOK2([5,4,1]))
    print(list2LinkedListFoldrImpOK3([5,4,1]))
    print(list2LinkedListFoldrImp([5,4,1]))
    
    1 回复  |  直到 4 年前
        1
  •  0
  •   Vorsprung    4 年前

    假设nums是1,2,3

          i = 0  
          for num in nums:
            ret[i+1] = lambda rs: ret[i](Node(num, rs))#---- i NOT captured !!
            i = i+1
          return ret[i](None)
    

    循环将设置ret[0:2],然后返回ret[3]

    我想这就是为什么它没有按预期工作的原因

    尝试返回 ret[0:i-1](None)