zoukankan      html  css  js  c++  java
  • python 进阶之路:绑定延迟

    看看下面一题,试着写出自己的答案。
    def multipliers():
        return [lambda x: i * x for i in range(4)]
    
    
    print([m(2) for m in multipliers()])
    print(type(multipliers()))
    
    
    res:
    
    [6, 6, 6, 6]
    <class 'list'>
    
    输出结果不是我们想的[0,2,4,6],这是为什么呢?如何输出我们想的结果呢?
    
    首先,上述问题产生的原因是python 闭包的延迟绑定。在这里你可能会有疑问
    ,什么是闭包?
    在python 的核心编程里,闭包定义如下:
    如果在一个内部函数里,对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被
    认定为闭包。
    总结为三点:
    1、是一个内嵌函数
    2、对外部函数变量的引用
    3、外部函数返回内嵌函数
    简单的闭包eg:
    def counter(start_at=0):
        count = [start_at]
        def incr():
            count[0] += 1
            return count[0]
        return incr
    
    继续刚才的问题,python 闭包的延迟绑定,意味着
    内部函数被调用,时,参数的值在闭包内进行查找。因此,
    当任何有multipliers()返回的函数被调用时,i 的值
    将在附近范围进行查找。那是不管返回函数是否被调用,for
    循环已经完成,i被赋予最终值3,因此,每次返回的函数乘以
    传递过来的值3 ,因为上段代码传过来的值是2,他们最终的返回都是6。
    
    
    以匿名函数的形式,看着你可能存在疑惑,现在为你转换成 for循环语句,
    便于你理解。
    
    def func():
        fun_list = []
        for i in range(4):
            def foo(x):
                return x*i
            fun_list.append(foo)
        return fun_list
    for m in func():
      print m(2)
    
    
    
    
    那现在考虑一下,如何输出我们想的结果【0,2,4,6】?
    两种方法为您推荐:
    方法一:
    def multipliers():
        for i in range(4): yield lambda x: i * x
    print([m(2) for m in multipliers()])
    print(type(multipliers()))
    
    res:
        [0, 2, 4, 6]
        <class 'generator'>
    
    方法二:
    
    def multipliers():
        return [lambda x, i=i: i * x for i in range(4)]
    
    
    print([m(2) for m in multipliers()])
    print(type(multipliers()))
    
    
    res:
    
        [0, 2, 4, 6]
        <class 'list'>
  • 相关阅读:
    如何面试你的面试官
    给老婆的一篇文章
    机器学习:选对时机直线超车
    面试技巧:带走面试官的节奏
    微信红包的随机算法是怎样实现的?
    全栈技术导图
    AI时代:推荐引擎正在塑造人类
    冲顶大会APP技术选型及架构设计
    多域名解析及延伸知识点
    在编程中为所欲为[圣诞版]
  • 原文地址:https://www.cnblogs.com/liangliangzz/p/14307045.html
Copyright © 2011-2022 走看看