零基础学 Python(2018 版)
尹会生
前游戏公司技术总监,前新浪网技术经理
80146 人已学习
新⼈⾸单¥68
课程目录
已完结/共 72 讲
第一章 :Python介绍和安装 (3讲)
第二章 :Python基础语法 (3讲)
第四章 :条件与循环 (5讲)
第五章 :映射与字典 (2讲)
第六章 :文件和输入输出 (2讲)
第七章 :错误和异常 (1讲)
第九章 :模块 (1讲)
第十章 :语法规范 (1讲)
第十一章 :面向对象编程 (4讲)
第十二章 :多线程编程 (2讲)
第十六章 :综合案例 & 结课测试 (1讲)
特别放送 (1讲)
零基础学 Python(2018 版)
登录|注册
留言
23
收藏
沉浸
阅读
分享
手机端
回顶部
当前播放: 28 | 闭包的定义
00:00 / 00:00
高清
  • 高清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.75x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看
01 | Python语言的特点
02 | Python的发展历史与版本
03 | Python的安装
04 | Python程序的书写规则
05 | 基础数据类型
06 | 变量的定义和常用操作
07 | 序列的概念
08 | 字符串的定义和使用
09 | 字符串的常用操作
10 | 元组的定义和常用操作
11 | 列表的定义和常用操作
12 | 条件语句
13 | for循环
14 | while循环
15 | for循环语句中的if嵌套
16 | while循环语句中的if嵌套
17 | 字典的定义和常用操作
18 | 列表推导式与字典推导式
19 | 文件的内建函数
20 | 文件的常用操作
21 | 异常的检测和处理
22 | 函数的定义和常用操作
23 | 函数的可变长参数
24 | 函数的变量作用域
25 | 函数的迭代器与生成器
26 | Lambda表达式
27 | Python内建函数
28 | 闭包的定义
29 | 闭包的使用
30 | 装饰器的定义
31 | 装饰器的使用
32 | 自定义上下文管理器
33 | 模块的定义
34 | PEP8编码规范
35 | 类与实例
36 | 如何增加类的属性和方法
37 | 类的继承
38 | 类的使用-自定义with语句
39 | 多线程编程的定义
40 | 经典的生产者和消费者问题
41 | Python标准库的定义
42 | 正则表达式库re
43 | 正则表达式的元字符
44 | 正则表达式分组功能实例
45 | 正则表达式库函数match与search的区别
46 | 正则表达式库替换函数sub()的实例
47 | 日期与时间函数库
48 | 数学相关库
49 | 使用命令行对文件和文件夹操作
50 | 文件与目录操作库
51 | 机器学习的一般流程与NumPy安装
52 | NumPy的数组与数据类型
53 | NumPy数组和标量的计算
54 | NumPy数组的索引和切片
55 | pandas安装与Series结构
56 | Series的基本操作
57 | Dataframe的基本操作
58 | 层次化索引
59 | Matplotlib的安装与绘图
60 | 机器学习分类的原理
61 | Tensorflow的安装
62 | 根据特征值分类的模型和代码
63 | 网页数据的采集与urllib库
64 | 网页常见的两种请求方式get和post
65 | HTTP头部信息的模拟
66 | requests库的基本使用
67 | 结合正则表达式爬取图片链接
68 | Beautiful Soup的安装和使用
69 | 使用爬虫爬取新闻网站
70 | 使用爬虫爬取图片链接并下载图片
强势回归:零基础学Python2022版来啦!
71 | 如何分析源代码并设计合理的代码结构&结课测试
本节摘要

课程源码、课件及课后作业地址:

https://gitee.com/geektime-geekbang/geekbangpython

登录 后留言

全部留言(23)

  • 最新
  • 精选
Geek_27b561
闭包计数器为什么要用列表? 用整数变量为啥传不进嵌套函数呢? 好像定义整数变量后,只要在嵌套函数里定义一下noblocal就可以了,这又是为啥……

作者回复: 这个问题非常好!首先我们先从nonlocal说起,python在使用变量的时候要遵循一个LEGB规则, 什么又是LEGB呢,就是如果你使用了一个函数内的变量做运算,python会从函数里面找这个变量的定义,如果找不到函数里面的定义就会报错了--即你看到的未定义先使用的错误了。 这种实现方式比js要好,避免在你忘记声明局部变量的时候,误使用了全局变量。 那变量都有几个作用域(影响范围)呢?一共是四个,分别是局部(local)-闭包(enclosing)-全局(global)-模块(builtin),LEGB就是取的他们的首字母; 如果要引用的变量的定义没在内部函数里面,而是在闭包里面就可以通过nonlocal声明一下,python就会从外层函数里面找这个变量的定义了,如果使用了global关键字修饰内部函数的变量,运算时就会从全局变量里面找变量的定义了。 上面说的是变量作用域,再来说下我为什么使用列表,这里使用列表的目的就是为了达到 nonlocal变量的功能,因为对列表的操作是直接操作内存的位置,对变量的操作是重新分配了一块新的内存; 所以在内部函数直接使用列表的名称也是操作外部函数定义的列表。这里需要通过python底层执行过程观察: from dis import dis # dis模块可以反汇编python函数的字节码 def counter2(first2=0): CNT2 = first2 def add_one(): # nonlocal CNT2 CNT2 += 1 return CNT2 return add_one dis(counter2(3)) 如果将nonlocal注释掉会显示反汇编结果为 LOAD_FAST 0 (CNT2) 如果不注释nonlocal或使用列表会显示反汇编结果为 LOAD_DEREF 0 (CNT2) LOAD_FAST 的含义是加载了本地变量 LOAD_DEREF 的含义是加载了引用的变量 LOAD_GLOBAL 的含义是加载了全局变量 这里涉及到python作用域和底层的一些原理,希望你能通过尝试更多的示例进行学习总结

2018-06-19
2
47
BeanNan
老师,我觉得你说的有些问题,如果闭包里面引用的变量的定义没有在闭包中,那么他也会去外层函数中去查找,直到查找到全局作用域,代码如下 cnt2 = 1 def counter(): def add_one(): a = cnt2 + 1 print(a) return a return add_one add_one = counter() add_one() #output 2 上述代码中输入2,说明在闭包中他是可以访问了全局的变量的,即使不用加nonlocal, 那么关于这段代码如下 def counter(): count = 1 def add_one(): count += 1 # error return count return add_one 那么上述代码报错原因,我也上网搜了一下,一个我可以理解的解释是,在闭包中count += 1,实际上是重新声明了一个count变量,覆盖了外层函数的count变量,那么此时这个count变量也没有被赋值,却参与到了运算当中,那么就会报错了,我也用老师说的反汇编测试过 老师,我这样理解的不知道对不对,请老师指点下,我用的python版本是3.7的

作者回复: 很细心,第一个问题我在解释的时候不严谨,如果函数内只引用全局变量,但不修改时可以不使用global关键字,一旦对全局变量进行修改必须声明,如:在函数内使用cnt2 += 1 就会报错了,这种情况下强制使用 global cnt2 显式声明才可以正常使用 def add_one(): global cnt2 # 声明 cnt2 += 1 # 对全局变量做修改 a = cnt2 + 1 print(a) return a 第二个问题的理解是对的,能够正确理解变量作用域对工作中有非常大的帮助,继续加油!

2018-07-02
10
我是,露莹
老师您好,我对def counter(FIRST = 0): cnt = [FIRST] 这一部分有点小疑惑,为什么传参FIRST = 0之后,如果counter()函数有传值就使用FIRST值,没有传值就默认为0呢? 这个FIRST = 0, 不是指将0赋值给FIRST,从此之后FIRST都等于0吗? 烦请老师解答,谢谢。

作者回复: 这里涉及函数执行的顺序问题,使用FIRST = 0作为参数,在定义函数时FIRST就得到了 0, 如果没有传值,那么FIRST就取得0了, 如果给函数传值,FIRST就会取得传递的值,覆盖掉0,FIRST就是新的值了

2019-04-19
4
Switch
闭包最初理解起来有点困难,特别是对写多了OOP代码的人。因为无法理解为啥要这么绕的去使用一个局部变量。 但是,一旦理解了“作用域”这个概念。 就能明白,无论是在面向过程开发中使用闭包,还是在面向对象编程中使用类。 都是为了在某一作用域下共享资源。

作者回复: 对的,因为面对初学者,我没有太理论化的解释作用域的问题。更多关于作用域的解释可以参考搜索引擎和我的其他留言回复。

2018-07-21
4
奋斗人生
关于闭包内部函数调用外部函数的列表时候,为什么调用cnt【0】的时候不需亚global声明呢? 不是说作用域只在函数内吗?

作者回复: 在函数中定义另一个函数称为嵌套函数,嵌套函数可以访问包围范围内的变量,所以不需要global声明

2020-08-20
2
1
快乐一家
本套教程只是讲解了很少的python内容,特别是python的内置函数,只是讲解了3个

作者回复: https://docs.python.org/zh-cn/3.7/library/functions.html 内置函数的官方文档我提供一下,主要给读者提供一个方法,逐一讲解就太啰嗦了

2020-03-27
1
鲁鲁
老师!闭包,变量b怎么传值使用?

作者回复: 因为视频里出现了多次传值,我不太清楚你的问题是指哪个代码,需要问题再详细一点,如果还是没搞明白传值的过程,可以补充一下问题,或者按照你的理解描述一遍问题,我来详细回答你

2022-01-15
luona187
老师,我用您的第二个解答在函数内使用 global 还是有报错,麻烦老师帮忙看看是哪里的问题。 代码如下: def counter(): cnt = 0 def add_one(): global cnt # 声明 cnt += 1 # 对全局变量修改 return cnt return add_one num5 = counter() print(num5()) 报错提示如下: Traceback (most recent call last): File "E:/luona/Python_study/test_func.py", line 173, in <module> num5 = counter(5) TypeError: counter() takes 0 positional arguments but 1 was given

作者回复: TypeError: counter() takes 0 positional arguments but 1 was given 注意这里,是不应该为counter带参数的,因为你定义这个函数的时候就没有指定变量来接收参数

2020-03-16
2
白开水
老师你好,我使用global变量进行了练习,为什么没有按照我传入的数字进行计数呢,还是按照初始赋值的变量的值进行计数,麻烦指点一下。 a = 0 b = 10 def counter(x,y): def add_one(): global a,b a += 1 b += 1 return a,b return add_one #老师为什么我传值之后不是按照2和20计数呢? num1 = counter(2,20) print (num1()) print (num1()) print (num1()) print (num1()) print (num1()) print (num1()) 输出结果:为什么没按照我传入的2和20开始计数? (1, 11) (2, 12) (3, 13) (4, 14) (5, 15) (6, 16)

作者回复: 因为声明的global a,b 就是全局变量初始化的 a = 0 b = 10 而且这里和x,y 没有必然联系,所以没有从2和20开始计数

2020-02-02
Serendipity
cnt[0] += 1;列表可以和 int 类型做加法运算吗??

作者回复: 要看 cnt[0] 是什么类型

2019-10-04
收起评论