issue-15 了解闭包里如何使用外围作用域里的变量
来源:互联网 发布:淘宝小样四大靠谱店 编辑:程序博客网 时间:2024/06/05 15:14
先来看一个例子,有一个列表,我们想要对它排序,但是呢,如果这个列表里的元素在另一个列表里,那么,这个元素有优先排序权,我们来写一个程序:
# -*- coding: utf-8 -*-
numbers = [3,6,1,2,4,9,7,8]group = [4,2,7]def sort_priority(values,group): def helper(x): if x in group: return (0,x) else: return (1,x) values.sort(key=helper) return valuesprint(sort_priority(numbers,group))
输出:
[2, 4, 7, 1, 3, 6, 8, 9]
我们一起来看下这个程序,首先先了解sort函数,对一个列表排序,直接list.sort(),如果想用自己定义的函数来排序,就是list.sort(key=func),所以这里的func就是helper函数,
这个函数的输入变量就是这个list中的每一个元素,执行完以后就会返回一个数组(0,x),对数组的排序,先看第一个元素,所以(1,6)是大于(0,7)的,这样就可以把在
第二个列表中的元素优先排序。
所以这个程序里的helper函数,就是闭包,闭包就是一种定义在某个作用域中的函数,这个函数引用了这个作用域中的变量,这个helper函数就是用了这个numbers列表中的变量
好的,我们继续看下假如我们设置一个flag,就是如果找到了这个元素在另一个列表里,我们就更改这个flag,否则不改,这样我们就知道到底最后有没有这种元素。
# -*- coding: utf-8 -*-numbers = [3,6,1,2,4,9,7,8]group = [4,2,7]def sort_priority(values,group): found = False def helper(x): if x in group: found = True return (0,x) else: return (1,x) values.sort(key=helper) return values, foundprint(sort_priority(numbers,group))
输出:
([2, 4, 7, 1, 3, 6, 8, 9], False)
这里就奇怪了,我们找到了啊,为啥这里found还是false呢,这里就是涉及到了闭包的作用域问题,当表达式中引用变量时,Python解释器会按照下面的顺序来遍历各个作用域,
以解析这个引用。
1.当前函数的作用域
2.任何外围作用域
3.包含当前代码的模块的作用域
4.内置作用域,就是那些内置函数(比如str,len,sort等)的作用域
如果这些都没有找到,就会抛出异常,nameerror。
给变量赋值时,规则有点不同,如果当前作用域已经定义了这个变量,那么这个变量就会被重新赋值,如果没有定义,那么就会认为这次赋值时一次定义加赋值操作,而新定义
的变量,其作用域就是当前的这个函数。
所以当我们在helper函数里进行一个赋值操作时,found=True,就相当于冲洗定义了一个found变量,并给他赋值,而不是在给外围作用域的found变量赋值,这个是Python故意这样设计
的,这样做可以防止函数中的局部变量污染函数外部的作用域和模块,如果不这样做,那么函数里的每一个赋值操作,都会影响外部的全局作用域,会混乱的。
那么我们如何才可以获取外部的变量呢?这里我们可以加一个声明就可以了,nonlocal found
# -*- coding: utf-8 -*-numbers = [3,6,1,2,4,9,7,8]group = [4,2,7]def sort_priority(values,group): found = False def helper(x): if x in group: nonlocal found found = True return (0,x) else: return (1,x) values.sort(key=helper) return values, foundprint(sort_priority(numbers,group))
输出([2, 4, 7, 1, 3, 6, 8, 9], True)
nonlocal语句清楚的声明,如果你要用到这个变量,你要知道这个变量时外围作用域中的,修改的就是外围作用域的变量。 但是nonlocal 很容易想全局变量那样遭到乱用,所以还是建议不要在复杂的函数里用,你想想,如果声明和引用相距比较远,那么你可能意识不到引用的是哪里的变量,调试会很麻烦。
总结一下:
对于定义在某个作用域中的函数,就叫闭包,它只可以引用这个作用域中的变量
使用默认赋值操作时,在闭包里的话,不会影响外围作用域中的变量
要使用外围作用域的变量,在Python 3 中可以用nonlocal声明一下,但是记住,我们只在简单的函数里这样使用。
阅读全文
0 0
- issue-15 了解闭包里如何使用外围作用域里的变量
- python里使用vars()返回当前局部作用域的所有成员函数和成员变量
- 如何了解 <![CDATA[ ]]>的作用?
- js-----初步了解变量 作用域
- 从外围了解UE4
- unity3d 使用c#如何访问某个对象里的c#脚本里的一个变量
- 代码大全学习-13-如何使用变量(General Issue in Using Variables)
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- iOS开发-版本管理常用git命令
- 从MultipartFile获取File式的inputStream
- Flink学习笔记 --- 理解DataStream WordCount
- 命令模式
- UVA 11549 Calculator Conundrum Floyd判圈算法 Brent判圈算法 相关性质及证明
- issue-15 了解闭包里如何使用外围作用域里的变量
- HorizontalScrollView 初始化第一次时使用smoothScrollTo无效的解决办法
- SOAPUI测试步骤(七)---DataSink TestStep
- shell脚本
- 括号匹配Java实现
- Java的回调
- 第三季第一节课——题目1
- Centos7.3安装和配置Mysql5.7
- c++ 双向链表