pickle.dump(obj, file, [,protocol])

3.6万
0
2023-06-28 22:30:35
6
投币
1
1
主要发布:数学思维与文化、少儿编程、发明创造、《新概念英语》背诵相关视频
4137.4万播放
简介
使用 IDLE 打开 datetime 模块的帮助文件
01:12
datetime 模块的最大、最小年份信息
00:58
datetime模块下有datetime类,有许多与日期时间相关的方法
00:55
使用TAB键打开datetime模块的帮助信息
00:53
datetime.today()方法返回当天的日期、时间信息
00:46
如何返回一个新的 set 包含 s1 和 s2 中不重复的元素?
00:34
Python中的lambda是什么?
00:21
迭代是Python最强大的功能之一,是访问集合元素的一种方式
00:24
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束
00:28
迭代器是一个可以记住遍历的位置的对象
00:32
迭代器有两个基本的方法:iter() 和 next()
00:51
字符串,列表或元组对象都可用于创建迭代器
00:44
iter()函数帮助信息
00:53
next()函数帮助信息
00:41
创建迭代器对象
00:28
迭代器对象不能用 print() 直接输出内容
00:37
可以输出迭代器对象
00:34
元组数据可以转换成迭代器
00:25
集合对象可以转换成迭代器
00:20
字典对象可以转换成迭代器
00:53
next()函数返回迭代器中的数据值
00:29
连续调用next()函数。遍历所有元素,最终返回异常
00:19
next()函数不能直接作用于列表对象
00:32
iter()函数可以把 range 对象转换成迭代器
00:44
创建迭代对象后用 for...in 循环遍历该对象
00:46
将字符串转换成迭代器
00:32
输出字符串迭代器的内容
00:39
列表对象也可以用 for...in 循环遍历
00:28
一个无限循环,遍历数据到头后抛出异常
01:36
再次分析-通过无限调用next()产生异常
01:25
Python 生成器 是难度较大的部分。需要深入了解
00:33
什么是函数。有些什么作用
01:40
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作
01:16
更简单点理解生成器就是一个迭代器
00:54
每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值
01:06
yield 生成器和 return 返回结果之间的区别
01:05
类比人类任务安排,对比生成器和函数的区别
01:12
下一次执行 next() 方法时从当前位置继续运行
00:34
生成器函数 - 斐波那契
01:47
f 是一个迭代器,由生成器返回生成
00:49
print() 输出生成器的地址
00:43
使用next()函数获取生成器的计算结果
01:27
可以选中next()函数连续计算函数的返回值
00:35
带参数的函数进行赋值后得到的是生成器对象
01:02
在变量管理器中看到生成器对象
00:57
函数直接返回结果,而生成器可以中途返回结果,并且保存函数上下文并继续运行
01:09
重新生成一个生成器。让生成器清零从头开始
00:39
无限循环调用生成器,直到抛出异常
01:32
使用生成器不断输出计算结果
00:56
不返回a,返回b也是没问题的
01:00
同列表相比,生成器的运行规则可以更复杂很多
01:38
生成器和函数调用的区别与联系
01:36
函数是组织好的,可重复使用的,用来实现单一或相关联功能的代码段
00:58
函数能提高应用的模块性和代码的重复利用率
00:44
你也可以自己创建函数,这被叫做用户自定义函数
00:42
自定义函数是任何编程语言的核心更能功能
00:50
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
00:50
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
00:43
函数内容以冒号起始,并且缩进
00:40
return [表达式] 结束函数,选择性地返回一个值给调用方、
00:38
不带表达式的 return 相当于返回 None
00:14
定义一个没有返回值的简单函数
00:37
Python 函数也需要使用 F9 加载内存中,然后才能调用
00:43
变量管理器中删除所有变量。则函数也会被删除,无法直接调用
00:43
定义一个有两个参数,有返回值的函数
00:27
输入两个参数调用 max() 函数返回结果
00:32
给max()函数 3-4 个参数依然正常运行
01:05
开始没有运行用户自定义的max()函数。我们实际调用的是系统内置的max()函数
00:47
系统优先调用用户自定义函数。而非系统函数
01:11
给用户自定义函数加上内部输出的字符串
01:32
清空内存之后调用的是系统函数。运行自定义函数代码之后,自定义函数优先
01:05
用户自定义函数不要使用系统函数名称
01:34
计算长方形面积函数
00:48
def print_welcome(name)
00:21
调用欢迎程序
00:28
调用面积计算函数
00:39
定义一个函数:给了函数一个名称,指定了函数里包含的参数和代码块结构
00:40
这个函数的基本结构完成以后,你可以通过另一个函数调用执行
00:22
也可以直接从 Python 命令提示符执行
00:38
定义函数def printme( str )
00:18
调用printme()函数
00:38
使用问号获取自定义函数帮助信息
00:44
使用help()函数获得自定义函数帮助信息
00:24
在自定义函数第一行写入帮助字符串
00:47
自定义函数第一行的注释信息可以使用单引号
00:24
使用问号可以得到自定义函数的帮助信息
00:41
使用help()函数可以得到自定义函数的帮助信息
00:22
Python 支持函数递归调用
01:09
阶乘运算的递归调用示例
00:52
阶乘运算的递归调用实例
00:46
通过递归调用实现字符串反转
00:48
为什么递归调用能够实现字符串反转
01:31
调用递归函数实现字符串反转
01:02
调用递归函数实现汉字字符串反转
00:48
在 Python 中,类型属于对象,变量是没有类型的
00:49
[1,2,3] 是 List 类型,加百力 是 String 类型
01:00
而变量 a 没有类型,她仅仅是一个对象的引用(一个指针)
00:29
变量没有类型,可以自由赋值。但也有很大的风险
00:40
可更改(mutable) 与 不可更改(immutable)对象
00:51
在 Python 中,strings, tuples, 和 numbers 是不可更改的对象
01:12
而 list,set,dict 等则是可以修改的对象
01:12
不可变类型:变量赋值 a=5 后再赋值 a=10。这里实际是新生成一个 int 值对象 10,再让 a 指向它。而 5 被丢弃,不是改变 a 的值,相当于
01:02
可变类型数据可以对部分数据值做修改。变量本身的地址不变
00:31
重新给变量赋值时,变量地址发生改变。生成了新的变量
00:39
修改单个列表元素数据。整个列表的地址没有改变
00:37
相同的列表变量名称,赋值不同的列表数据,地址会发生明显的变化
00:51
相同的变量名和数据多次赋值,得到的地址不同
00:54
重启内核前后,相同变量名,相同数据的地址不同
01:08
整型变量,多次赋值后地址相同
00:34
重启内核之后。相同变量和整数值的地址保持不变
01:18
为什么相同的列表和整数,赋值之后,前者地址不断改变,后者地址始终不变
00:32
元组数据,连续赋值,地址来回改变
01:19
字符串数据,连续赋值,地址不断改变
00:33
Python 函数的参数传递规则。有的函数无参数,有的函数有参数
00:45
不可变类型的参数传递。不会修改传进来的参数
00:38
可变类型:类似 C++ 的引用传递,如 列表,字典
00:49
Python 中一切都是对象,所以不能说 值传递 还是 引用传递
00:23
应该说传 不可变对象 和传 可变对象
01:24
Python 传递不可变对象。通过 id() 函数来查看内存地址变化
00:25
def change(a) 定义一个函数修改变量地址
01:07
外部程序示例代码。传递不可变参数,函数内部做修改
01:07
传递不可变对象。函数测试结果
01:51
解释传递不可变对象,为什么没有改变对象的数值
01:26
加入输出语句后。看的更清楚了。不可变对象没有改变
01:41
可以看见在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同)
00:32
在函数内部修改形参后,形参指向的是不同的 id
00:37
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了
00:27
定义一个传入可变对象的函数
00:46
外部程序。测试传入可变对象会有什么结果
00:41
传入可变参数,查看结果的示例代码。果然在外部,参数也改变了
00:55
四个地址数据完全一致
00:34
传入可变对象,对象被改变的本质原因
01:03
传入不可变对象和可变对象的地址分析
01:13
在函数 printme() 调用时使用参数名
00:31
两个参数时,第一个正常输出,第二个以元组方式输出
00:34
只有一个参数的情况下,第一个参数正常输出,第二个输出的是空元组
00:26
第一个参数正常输出,后两个参数以元组形式输出
00:23
分析包含不定长参数的函数
00:45
定义一个包含了不定长参数的函数
00:38
加了星号的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
00:51
不定长参数的一般形式
00:47
不定长参数介绍
00:31
函数定义时默认参数不能放在一般参数的前面
00:56
介绍print()函数的默认值参数
00:48
用户如果明确给定了参数值则使用用户输入的参数
00:35
用户没有给定参数则使用默认参数
00:21
定义一个带有默认参数的函数
00:30
调用函数时,如果没有传递参数,则会使用默认参数
00:16
直接输入参数数据,没有任何问题
00:45
调用时有参数名称,顺序可以打乱
00:43
定义了两个输入参数的函数
00:31
关键字参数指定了参数名称,可以随意调整参数位置
00:57
位置参数必须放在关键字参数前面
01:09
使用print()函数展示关键字参数
01:06
关键字参数。将数据赋值给参数
00:48
包含参数的函数示例代码
00:41
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值
00:28
输入整数,查看调用情况
00:28
调用 printme 函数,不加参数会报错
00:27
介绍printme()函数并正常调用
00:59
必需参数 须以正确的顺序传入函数。调用时的数量必须和声明时的一样
00:29
Python 调用函数时可使用的四种正式参数类型
00:23
函数注释字符串可以放在程序的后几行,前面是空格也没问题
01:10
如果在函数调用时没有指定参数,它就是一个空元组
00:14
拆分不定长参数为单个数据
00:39
定义包含不定长参数的函数。逐个输出不定长参数值
00:56
不定长参数函数,只有一个数据的情况
00:19
不定长参数函数。通过 for...in 方式遍历元组数据
00:21
带有两个星号的不定长参数
00:26
加了两个星号的参数会以字典的形式导入
00:13
加一个星号和两个星号的参数,导入参数的方式不同
00:43
带有两个星号的不定长参数的函数
00:47
定义一个带两个星号的不定长参数的函数
00:42
输入参数调用不定长参数函数(两个星号标记)
01:24
不能直接输入数据调用函数
00:52
带两个星号的不定长变量,需要关键字传入参数的方式
01:07
声明函数时,参数中星号可以单独出现
00:43
单独出现星号后的所有参数都必须用关键字传入
00:32
这个函数还是只有 3 个参数。但第 3 个参数 c 必须靠关键字方式引入
00:38
实际上还是3个参数。星号并不是一个参数
00:35
错误的调用方式
00:40
c 必须使用关键字传入数据
00:21
使用新的关键字参数 d 传入参数出错
00:25
星号后面可以接多个参数。但都必须以关键字形式传入数据
00:27
星号后面的多个参数都必须以关键字模式传入数据
00:38
最后一个参数 4 出现错误
00:34
d 必须使用关键字传入数据
00:26
两种不定长参数的区别
00:55
独立星号,标示后面的参数必须以关键字方式引入
00:43
Python 使用 lambda 来创建匿名函数
00:21
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数
00:37
lambda 只是一个表达式,函数体比 def 简单很多
00:23
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去
00:29
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数
00:36
lambda 函数拥有自己的命名空间。且不能访问自己参数列表之外或全局命名空间里的参数
00:29
内联函数的目的是调用小函数时不占用栈内存从而增加运行效率
00:18
lambda 函数的一般形式
00:24
lambda函数让代码看起来更简洁直观
01:07
关键词lambda定义了一个匿名函数,冒号前面的是匿名函数的参数
00:36
lambda函数也是一个函数对象,所以也可以赋值给一个变量
00:52
lambda函数也作为返回值返回
00:41
有时我们需要在程序的某个位置使用一次某个函数,这个时候使用lambda函数更加的方便也便于理解
00:17
Python对lambda函数有限制,其中一个就是只允许lambda函数有一条表达式
00:24
定义一个lambda表达式
00:21
查看 sum 的类型。也是函数
00:15
调用 sum 函数
00:24
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式
00:30
不带参数值的 return 语句返回 None
00:12
定义一个函数,分析返回值
00:24
函数返回了一个结果None
00:35
定义一个计算两个参数之和的函数
00:35
调用sum函数并赋值给外部变量。内外两个变量的地址相同
01:08
即使变量名不同,内外地址还是相同
00:52
Python3.8 新增了一个函数形参语法 斜杠(除法符合)用来指明函数形参必须使用指定位置参数
00:30
形参 a 和 b 必须使用指定位置参数。因为他们都在 斜杠 之前
00:26
c 或 d 可以是位置形参或关键字形参
00:26
而 e 或 f 要求为关键字形参
00:15
定义一个参数比较复杂的函数
00:49
f(10, 20, 30, d=40, e=50, f=60)
00:31
b 不能使用关键字参数的形式
00:30
a 不能使用关键字参数的形式
00:32
e 必须使用关键字参数的形式
00:30
在前面的几个章节中我们脚本上是用 Python 解释器来编程
00:47
如果你从 Python 解释器退出再进入,那么你定义的所有的方法和变量就都消失了
00:39
为此 Python 提供了一个办法,把这些定义存放在文件中
00:21
为一些脚本或者交互式的解释器实例使用,这个文件被称为模块
00:22
多个系统模块我们早已经熟悉了
00:50
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py
00:24
模块可以被别的程序引入,以使用该模块中的函数等功能
00:39
这也是使用 Python 标准库的方法
00:49
生成 using_sys.py 脚本文件
01:04
查看 sys 模块的帮助信息
02:31
python using_sys.py 参数1 参数2
00:28
在控制台直接运行程序。提示程序文件找不到
00:38
pwd 显示当前工作目录发现问题
00:53
通过 spyder 上部的下拉菜单实行工作目录转换
00:43
双反斜杠表示目录层级,第一个反斜杠是转义字符
00:45
修改当前工作目录之后,运行脚本成功
01:00
sys.path 得到系统路径信息。信息保存在列表中
00:32
import sys 引入 python 标准库中的 sys.py 模块。这是引入某一模块的方法
00:21
sys.argv 是一个包含命令行参数的列表
00:18
实验证明 sys.argv 是一个列表对象
00:23
sys.path 包含了一个 Python 解释器自动查找所需模块的路径的列表
00:46
想使用 Python 源文件,只需在另一个源文件里执行 import 语句
00:17
当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入
00:42
搜索路径是一个解释器会先进行搜索的所有目录的列表
00:40
如想要导入模块 support,需要把命令放在脚本的顶端
00:28
support.py文件内容介绍
00:39
导入 support.py 模块失败。估计是路径问题
00:41
sys.path 路径中确实没有我们当前的这个工作目录
00:36
打开cmd程序,运行指定脚本,并查看sys.path路径信息
01:10
有了import可以一次性导入大量函数,而不用先运行一下,加载到内存中
00:52
无法导入support的原因是路径问题。提出增加sys.path路径的思路
01:09
针对sys.path列表,添加新路径的方法取得成功
00:56
在sys.path列表中加入新地址,可以导入support.py库
00:25
重启spyder之后,再次导入support模块失败
01:17
重启spyder之后,前面添加的路径失效
00:43
设置工作目录为当前目录,成功导入support库
00:36
工具 - PYTHONPATH管理。可以添加新目录
01:10
一个模块只会被导入一次,不管你执行了多少次 import
00:33
当我们使用import语句的时候,Python解释器是怎样找到对应的文件的呢?
00:24
这看起来很像环境变量,事实上,也可以通过定义环境变量的方式来确定搜索路径
00:31
搜索路径是在 Python 编译或安装的时候确定的,安装新的库应该也会修改
00:34
搜索路径被存储在sys模块中的path变量
00:36
sys.path 输出是一个列表,其中第一项是空串''。代表当前目录
00:45
若是从一个脚本中打印出来的话,可以更清楚地看出是哪个目录
00:29
在cmd中实验。从脚本中打印 sys.path 可以看到当前目录
01:03
因此若像我一样在当前目录下存在与要引入模块同名的文件,就会把要引入的模块屏蔽掉
00:35
了解了搜索路径的概念,就可以在脚本中修改sys.path来引入一些不在搜索路径中的模块
00:18
在解释器的当前目录或者 sys.path 中的一个目录里面来创建一个fibo.py的文件
00:22
斐波那契(fibonacci)数列模块
01:04
fib(n)函数介绍。定义到 n 的斐波那契数列
01:11
fib2(n)函数分析。返回到 n 的斐波那契数列
01:00
然后进入 Python 解释器,使用下面的命令导入这个模块
00:45
这样做并没有把直接定义在 fibo 中的函数名称写入到当前符号表里。只是把模块fibo的名字写到了那里
00:16
使用模块名称 fibo 调用函数成果
00:57
直接调用fib()函数失败。函数名称还不在当前符号表里面
00:52
fibo.fib2(100)调用成功
00:20
math、sys模块导入之后,调用函数还是需要模块名称
01:23
目前 fibo 属于module类型
00:34
导入fibo模块之后,使用TAB键可以看到函数列表
00:37
type(fibo.fib)是模块中的函数
00:24
可以使用问号查看 fibo 模块的帮助信息
01:03
dir(fibo)查看模块中的名称
00:35
help(fibo)查看系统帮助信息
01:05
help()帮助信息很多都是自动生成的
01:29
如果你打算经常使用一个函数,你可以把它赋给一个本地的名称
00:51
type(fib)类型还是函数
00:24
from … import 语句。from 语句从模块中导入一个指定的部分到当前命名空间中
00:24
from modname import name1[, name2[, ... nameN]]
00:25
from math import ceil 从模块中导出函数使用
00:59
from math import pi。从模块中导出常数
00:28
from math import pi,ceil。可以同时导出常数和函数
00:33
要导入模块 fibo 的 fib 函数。这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来
00:28
把一个模块的所有内容全都导入到当前的命名空间也是可行的
00:18
3这提供了一个简单的方法来导入一个模块中的所有项目。但是这种声明不该被过多地使用
00:26
模块除了方法定义,还可以包括可执行的代码
00:35
这些代码一般用来初始化这个模块。这些代码只有在第一次被导入时才会被执行
00:46
每个模块有各自独立的符号表,在模块内部为所有的函数当作全局符号表来使用
00:30
模块的作者可以放心大胆的在模块内部使用这些全局变量,而不用担心把其他用户的全局变量搞混
00:30
也可以通过 modname.itemname 这样的表示法来访问模块内的函数
00:24
模块是可以导入其他模块的
00:39
在程序最开始导入模块并不是强制的。只是一种惯例
01:08
被导入的模块的名称将被放入当前操作的模块的符号表中
00:36
还有一种导入方法,可以使用 import 直接把模块内(函数,变量的)名称导入到当前操作模块
00:23
from fibo import fib, fib2。直接使用函数
00:43
这种导入的方法不会把被导入的模块的名称放在当前的字符表中
00:26
为了验证模块没有导入当前符号表中,首先重启IPython内核
00:23
函数成功导入当前环境。模块不在当前环境中
00:54
只是导入函数的模式,不会导入模块
00:40
这还有一种方法,可以一次性的把模块中的所有(函数,变量)名称都导入到当前模块的字符表
00:18
from fibo import 星号。一次导入所有函数和变量
00:26
这将把所有的名字都导入进来,但是那些由单一下划线(_)开头的名字不在此例
00:15
大多数情况,Python 程序员不使用这种方法。因为引入的其它来源的命名,很可能覆盖了已有的定义
00:48
从math模块中导入全部函数和变量,结果本地定义的变量被覆盖
01:24
通过变量管理器查看导入的变量名称
00:34
一个模块被另一个程序第一次引入时,其主程序将运行
00:32
可以用__name__属性来使该程序块仅在该模块自身运行时执行
00:25
新建一个 using_name.py 文件
00:57
F5 运行脚本。发现程序自身在运行
00:37
导入模块时显示来自另一个模块
00:51
导入模块时有程序运行
00:57
Spyder平台可以用上面的 播放 按钮运行代码
00:28
第二次导入模块,没有运行程序
01:04
每个模块都有一个__name__属性
00:36
通过dir()函数验证每个模块都要__name__属性
00:43
当其值是'__main__'时,表明该模块自身在运行,否则是被引入
00:42
输出 __name__ 属性数据
00:54
import 导入模块时 __name__ 属性得到的结果是 using_name
00:28
__name__ 与 __main__ 底下是双下划线
00:39
导入模块是 print() 函数确实运行了
00:46
同R语言类似。模块文件本质是脚本文件,有可执行代码就会运行
00:51
输出 __file__ 属性数据
00:51
输出 __file__ 属性数据
00:30
输出 __package__ 属性数据。目前没有内容
00:27
输出 __spec__ 属性数据。注释掉前面所有内容之后运行代码得到的结果是 None
00:27
取消前面的注释,可以运行代码 __spec__ 属性数据发生变化
00:34
import using_name 可以看到模块中相关的输出信息
00:57
如果有导入模块可以在运行脚本时看到
01:03
导入几个系统模块,再运行脚本。目前看不到其他加载模块信息
01:04
import 逗号表达式。一次加载一组模块
00:36
dir() 函数查看对象中包含的字符串的名字
00:35
内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回
00:16
如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称
00:16
查看列表对象的方法
00:44
dir() 查看字符串对象中定义的各种方法
01:21
导入 fibo 模块之后,查看模块的属性和方法
00:27
导入math()库,用dir()查看模块中定义的
00:55
dir()函数和TAB获取帮助作对比
01:20
得到一个当前运行环境中定义的各种名称
01:42
dir()没有任何参数时,罗列出当前定义的所有名称
01:12
定义一个变量a=5。dir()马上可以看到该变量
01:08
del 删除变量之后,dir()函数看不到变量名称了
00:55
如果我们定义一个函数,dir()能否看到
00:45
定义一个myprint()函数,并加载到内存中成功
00:37
定义一个不做任何工作的函数来做实验
01:31
dir() 可以看到自定义函数的名字
00:46
del 能否删除函数名称呢?提出有趣问题
00:44
能够使用 del 删除自定义函数
00:21
del 是否能够删除系统内置函数?提出有趣问题
00:22
测试 del 能否删除系统内置函数。答案是不可以
01:17
max()内置函数的类型是:builtin_function_or_method
00:35
自定义函数的类型是 function
00:47
给内置函数赋值,转换成某种数据类型之后,可以用 del 删除该变量
01:29
变量被删除之后,max 重新变成内置函数,可以正常使用
01:35
删除变量之后,max 又变成了系统内置函数,可以正常使用
00:59
del 删除自定义函数之后。dir()函数无法查到
00:53
再次加载函数到内存中。使用变量管理器的橡皮擦删除所有变量和函数
01:11
十分有趣。这些变量名称保存在系统变量 _ 里面
00:48
此时系统变量 _ 的结果变为 100
00:19
生成用户自定义类又会如何?-有趣问题
00:37
定义一个不做任何事情的类,myclass()
00:29
变量管理器中看不到我们自定义的类,myclass()
00:28
尝试使用dir()函数查看我们自定义的类
00:48
可以使用 del 删除自定义类
00:52
删除自定义类之后 dir() 无法看到这个类的存在
00:19
能否删除导入的外部模块中的变量、方法、模块?
00:55
比如 math 库中的变量、方法,甚至整个模块
00:31
导入math模块之后可以看到该模块,也可以查看math模块内部的变量和方法
00:49
可以使用 del 删除模块中的某个变量
01:07
dir()查看模块,变量已经被删除
00:27
del 删除模块中的方法成功
01:12
dir()查看模块,发现ceil()方法已经被删除
00:21
再次 import math 删除的变量和方法是否会出现
00:33
被删除的变量、方法,并没有因为再次 import math 而出现
00:41
调用被删除的变量和方法,仍然不存在
00:38
在一个程序里面重复 import 不会多次加载运行同一个模块
00:37
del 删除导入的模块没问题
00:56
dir() 看不到math模块。已经被删除了
00:35
再次导入math模块。前面删除的变量和方法还是没有
01:13
变量管理器清空所有变量、自定义函数。然后导入math库,还是没有那些变量和方法
00:50
重启IPython内核之后,再次导入,没有任何问题
00:44
Python 本身带着一些标准的模块库
00:20
有些模块直接被构建在解析器里,这些不是一些语言内置的功能
00:55
这些组件会根据不同的操作系统进行不同形式的配置
00:48
比如 winreg 这个模块就只会提供给 Windows 系统
00:23
应该注意到这有一个特别的模块 sys ,它内置在每一个 Python 解释器中
01:05
变量 sys.ps1 和 sys.ps2 定义了主提示符和副提示符所对应的字符串
00:21
import sys 模块,查看提示符
00:59
包是一种管理 Python 模块命名空间的形式,采用 点模块名称
00:20
包可以看作是多个模块的集合
01:23
采用点模块名称这种形式也不用担心不同库之间的模块重名的情况
00:45
这样不同的作者都可以提供 NumPy 模块,或者是 Python 图形库
00:39
不妨假设你想设计一套统一处理声音文件和数据的模块(或者称之为一个 包)
00:43
所以你需要有一组不断增加的模块,用来在不同的格式之间转换
00:40
所以你需要有 一组不断增加 的模块,用来在不同的格式之间转换
00:36
这里给出了一种可能的包结构(在分层的文件系统中)
01:12
在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录
00:34
目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包
00:31
主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块
00:45
最简单的情况,放一个空的__init__.py就可以了
00:24
当然这个文件中也可以包含一些初始化代码或者为(将在后面介绍的) __all__变量赋值
00:32
用户可以每次只导入一个包里面的特定模块
00:17
这将会导入子模块:sound.effects.echo。 他必须使用全名去访问
00:37
直接导入子模块:from sound.effects import echo
00:22
这同样会导入子模块:echo,并且他不需要那些冗长的前缀,所以他可以这样使用
00:31
echo.echofilter(input, output, delay=0.7, atten=4)
00:30
还有一种变化就是直接导入一个函数或者变量
00:31
echofilter(input, output, delay=0.7, atten=4)
00:37
注意当使用 from package import item 这种形式的时候。对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,
00:44
import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入
00:24
包和子包本质上是目录,模块是具体的Python脚本文件
00:36
如果还没找到,抛出一个 ImportError 异常
00:32
反之,如果使用形如 import item.subitem.subsubitem 这种导入形式,除了最后一项,都必须是包
00:16
而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字
00:13
输出格式美化
00:48
Python 有两种输出值的方式:表达式语句 和 print() 函数
00:12
现有两种输出方式的举例
01:04
第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用
00:17
如果你希望输出的形式更加多样,可以使用 str.format() 函数来格式化输出值
00:20
定义字符串,调用format()方法
00:41
分析format()函数的参数
01:38
如果你希望将输出的值转成字符串,可以使用 repr() 或 str() 函数来实现
00:21
字符串转换函数 str() 举例
01:14
str()函数返回一个用户易读的表达形式
00:21
str()的参数是一个表达式的时候,先计算表达式的结果再输出结果的字符串
00:42
repr()产生一个解释器易读的表达形式
00:25
repr()函数帮助信息
00:52
eval(repr(obj)) == obj 实际测试
00:54
str(s) 同 repr(s) 函数转换的结果不同
00:28
变量管理器中发现,两个字符串的长度不一致
00:52
a == b,转换后的两个字符串不一样
00:22
str()计算1除以7的结果是一个浮点数字符串
00:31
1除以7是无限循环小数
00:30
算术表达式的计算结果通过 repr() 函数处理之后再生成字符串并输出
00:53
repr() 函数可以转义字符串中的特殊字符
00:30
变量管理器中查看两种字符串的区别
00:53
repr()函数的结果更适合解释器查看和处理
00:47
repr() 的参数可以是 Python 的任何对象
00:46
repr()中可以处理 range() 类型数据
00:12
str()也可以处理多种Python的对象
00:24
输出一个平方与立方的表-代码分析
01:06
输出一个平方与立方的表-代码展示
00:32
输出一个平方与立方的表 - 代码分析
01:30
输出一个平方与立方的表-修改代码
01:29
输出一个平方与立方的表-format()方法实现-代码介绍
01:09
for循环输出平方与立方表。format()方法实现功能
00:36
这个例子展示了字符串对象的 rjust() 方法, 它可以将字符串靠右, 并在左边填充空格
00:28
还有类似的方法, 如 ljust() 和 center()
00:17
使用ljust()左对齐方式格式化字符串
00:28
左对齐方式输出数据-效果展示
00:14
这些方法并不会写任何东西, 它们仅仅返回新的字符串
00:27
zfill(), 它会在数字的左边填充 0
00:14
'12'.zfill(5)
00:28
'-3.14'.zfill(7)
00:23
'3.14159265359'.zfill(5)
00:18
str.format() 的基本使用。括号及其里面的字符 (称作格式化字段) 将会被 format() 中的参数替换
00:16
格式化字段中,大括号的位置用于填入带输出的数据
00:48
在括号中的数字用于指向传入对象在 format() 中的位置
00:30
正常顺序输出format()中提供的参数
00:17
调整顺序让数据输出
00:26
format() 中使用了关键字参数, 那么它们的值会指向使用该名字的参数
00:48
用关键字方式输入数据,并在指定位置输出出来
00:29
以关键字方式给format()方法提供参数。参数位置就无关紧要了
00:23
关键字方式提供参数,输出数据
00:18
位置及关键字参数可以任意的结合
00:27
位置及关键字参数,混合使用输出数据
00:22
!a (使用 ascii()), !s (使用 str()) 和 !r (使用 repr())
00:21
输出 math.pi 的常量结果
00:33
!r调用repr()函数处理数据再输出
00:22
调用repr()输出math.pi
00:27
可选项:格式标识符可以跟着字段名。这就允许对值进行更好的格式化
00:54
对浮点数进行格式化设置与输出
00:21
精确到小数点后第3位输出math.pi
00:21
在 :后传入一个整数, 可以保证该域至少有这么多的宽度
00:21
在冒号后面设置数据宽度。为输出字典数据做准备
00:55
冒号后面提供字符串和整数的输出宽度
00:52
格式化字符串非常长时,格式化时通过变量名而非位置会是更好的方式
00:17
最简单的就是传入一个字典, 然后使用方括号 [] 来访问键值
00:14
传入字典数据的格式化字符串输出
00:34
传入字典数据后格式化输出数据
00:23
也可以通过在 table 变量前使用 两个星号 来实现相同的功能
00:12
引入字典数据时,使用两个星号做标记
00:16
两个星号指示字典类型参数,输出数据
00:53
百分号 操作符也可以实现字符串格式化
00:20
将左边的参数作为类似 sprintf() 式的格式化字符串, 而将右边的代入
00:17
使用传统方法输出math.pi。精确到小数点后3位
00:22
因为 str.format() 是比较新的函数, 大多数的 Python 代码仍然使用 百分号 操作符
00:31
但是因为这种旧式的格式化最终会从该语言中移除, 应该更多的使用 str.format()
00:16
下一个小节我们重点讲文件读写这个极其重要的知识集合
00:52
内置函数 open() 将会返回一个 file 对象
00:24
open()函数帮助信息
00:44
open(filename, mode)参数介绍
00:22
有十几种访问文件的方式,种类繁多
01:01
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式
00:22
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头
00:20
r+ 打开一个文件用于读写。文件指针将会放在文件的开头
00:16
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头
00:24
w 打开一个文件只用于写入
00:24
wb 以二进制格式打开一个文件只用于写入
00:31
w+ 打开一个文件用于读写
00:28
wb+ 以二进制格式打开一个文件用于读写
00:18
a 打开一个文件用于追加
00:19
ab 以二进制格式打开一个文件用于追加
00:23
a+ 打开一个文件用于读写
00:15
ab+ 以二进制格式打开一个文件用于追加
00:14
可以按照文件类型分类,也可以按照对文件的操作分类
00:18
可以把文件分成普通文件和二进制文件两种类型
00:33
按照对文件的操作可以分类为:读取、写入、追加,三种模式
00:19
默认是在该脚本程序所在的目录下生成文件
00:24
open()函数的两个参数介绍
00:56
为什么打开文件的默认模式是 r
00:26
生成文件对象
00:31
文件对象的类型是:_io.TextIOWrapper
00:28
变量管理器可以查看文件对象
00:47
write()方法在文件中写入信息
00:33
打开文本文件,发现成功写入数据
00:30
该方法的返回值是写入文件的字符数量
00:33
写入六个新的字符返回结果是6
00:24
打开文本文件发现没有写入内容。原来是路径有问题
00:38
修改目录为当前目录。打开文件写入数据
00:26
成功在当前目录生成文件,并写入数据
00:40
f.close() 关闭文件对象
00:18
关闭文件对象后,文件对象依然存在
00:36
f.closed 判断文件对象是否关闭
00:26
生成文件对象,查看帮助信息
01:13
通过 TAB 发现文件对象的方法非常多
01:08
在编程界面使用TAB键更能看出对象方法和属性信息
01:10
打开文件,写入数据,关闭文件全过程
01:29
调用 f.read(size), 读取一定数目的数据, 然后作为字符串或字节对象返回
00:23
f.read()方法的帮助信息
01:11
size 是一个可选的数字类型的参数
00:28
以下实例假定文件 tmp.txt 已存在(上面实例中已创建)
00:21
读取文本文件内容并展示
00:42
f.readline() 会从文件中读取单独的一行
00:22
f.readline() 如果返回一个空字符串, 说明已经已经读取到最后一行
00:10
打开文件,读取一行数据
00:26
f.readline()帮助信息
00:46
f.readlines() 将返回该文件中包含的所有行
00:18
f.readlines()帮助信息
00:39
如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割
00:34
读取文件中每一行数据
00:39
f.readlines()方法将每行数据都作为列表的一项,方便处理
00:56
查看从文件中读取出来的列表项
00:51
另一种方式是迭代一个文件对象然后读取每行
00:21
遍历文件对象的方式来输出文件内容
01:14
f.write(string) 将 string 写入到文件中, 然后返回写入的字符数
00:14
f.write()在文件中写入字符串。返回实际写入的数据量
00:31
如果要写入一些不是字符串的东西, 那么将需要先进行转换
00:21
非字符串数据需要先进行转换,然后才写入文件
00:32
打开文件发现元组数据以字符串的形式写入文件
00:22
write()写入元组数据出错。只能写入字符串数据
01:29
f.tell() 返回文件对象当前所处的位置, 它是从文件开头开始算起的字节数
00:21
文件中没有任何数据,前期写入数据出错。f.tell()还是在文件开始的位置
00:34
读取文件成功,f.tell()方法返回当前文件指针的位置
00:49
如果写入文件后没有关闭文件对象,能否同时打开文件对象读取数据?
00:20
打开文件写入数据后不关闭文件对象,再次打开文件读取数据,没有问题
00:36
如果要改变文件指针当前的位置,可以使用 f.seek(offset, from_what) 函数
00:37
f.seek(offset, from_what)有两个参数
00:34
from_what 的值,如果是 0 表示开头,如果是 1 表示当前位置,2 表示文件的结尾
00:56
seek(x,0) ; 从起始位置即文件首行首字符开始移动 x 个字符
00:26
seek(x,1) ; 表示从当前位置往后移动x个字符
00:10
seek(-x,1) ; 表示从当前位置往前移动x个字符
00:25
seek(-x,2) ; 表示从文件的结尾往前移动x个字符2
00:31
from_what ; 值为默认为0,即文件开头
00:17
以二进制方式读写文件,写入原始数据
00:27
tmp.txt文件以二进制字节形式写入了数据
00:38
移动到文件的第六个字节
00:41
移动到文件的倒数第三字节
00:38
当你处理完一个文件后, 调用 f.close() 来关闭文件并释放系统的资源
00:26
如果尝试再调用该文件,则会抛出异常
00:34
尝试读取已经关闭的文件会出现错误-示例代码
00:19
当处理一个文件对象时, 使用 with 关键字是非常好的方式
00:26
而且写起来也比 try - finally 语句块要简短
00:35
只要写了 open() 就马上写一个 close() 保持成对出现
00:57
成对编写代码的方式在其他编程语言中也经常使用
00:42
打开文件,写入字符串之后关闭文件对象
00:36
手动打开文件,发现成功写入字符串
00:22
使用 with 打开文件并读取数据
00:42
输出 read_data 看是否读取成功
00:23
读取文件内容成功。并且也关闭了文件对象
00:23
要读取文件必须保证文件存在。否则会抛出异常
00:47
Python 的 pickle 模块实现了基本的数据序列和反序列化
00:19
通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储
00:21
通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象
00:28
write() 只能写入字符串,不能写入其他对象
00:48
pickle.dump(obj, file, [,protocol])
00:35
有了 pickle 这个对象, 就能对 file 以读取的形式打开
00:42
import pickle 导入模块,并查询是否存在
00:17
查看 pickle 的帮助信息
01:32
生成字典类型数据 data1
00:58
变量管理器看到data1确实是字典类型数据
00:23
小括号、中括号、大括号中的数据不用续行符也能写成多行
00:45
因为字典数据复杂,所以故意写成多行形式
00:26
Python 重点支持短小精悍的句子。不宜写的太长
00:49
生成列表数据,并在末尾添加它自己
00:14
输出列表数据并查看内容
00:26
测试列表数据长度并分析内容
00:19
以二进制写入方式打开文件,准备写入对象
00:32
pickle.dump()函数帮助信息
01:18
pickle.dump(data1, output)写入数据成功
00:16
通过零号协议,将数据写入了文件
00:30
使用可用的最高级别的协议写入列表数据到文件中
00:32
将列表写入文件后关闭文件对象
00:12
字典和列表数据都是以二进制方式写入文件
00:34
将字典和列表数据写入文件,详细分析
00:40
import pprint, pickle
00:28
查询 pprint 模块的帮助信息
00:59
使用pickle模块从文件中重构 Python 对象
00:26
手动记事本打开,发现里面全是乱码。需要使用特定模块,单独处理
00:34
pkl_file = open('data.pkl', 'rb')。生成文件对象成功
00:27
BufferedReader 对象同之前我们操作的文本对象不同
00:55
data1 = pickle.load(pkl_file)。加载第一个数据到内存变量中
00:40
print(data1) 输出数据看是否成功加载字典数据
00:24
pprint.pprint(data1) 输出字典数据
00:23
data2 = pickle.load(pkl_file) 装载列表对象成功
00:25
print(data2) 列表数据成功输出
00:10
pprint.pprint(data2) 输出列表数据成功
00:29
pprint()函数帮助信息
00:58
完成Python对象装载之后,管理文件对象
00:45
打开二进制文件,从文件中加载数据到内存变量中
01:28
pickle 模块 4 个方法的分析
01:11
dumps()和loads()分析
00:35
Python 3 File(文件)对象的方法
00:27
内置函数 open() 用于打开一个文件,并返回文件对象
00:39
在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError
00:38
注意:使用 open() 函数一定要保证关闭文件对象,即调用 close() 方法
00:30
open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)
00:49
open(file, mode='r')
00:13
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None,
00:31
file:必需,文件路径(相对或者绝对路径)
00:33
mode:可选,文件打开模式
00:41
buffering:设置缓冲
00:10
encoding:一般使用utf8
00:24
errors:报错级别
00:12
newline:区分换行符
00:19
closefd:传入的file参数类型
00:21
opener:设置自定义开启器,开启器的返回值必须是一个打开的文件描述符
00:14
file.close() 关闭文件。关闭后文件不能再进行读写操作
00:28
file.flush() 刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入
00:28
file.fileno() 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上
00:19
返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如 os模块的read方法等一些底层操作上
00:37
file.isatty() 如果文件连接到一个终端设备返回 True,否则返回 False
00:15
很多编程语言都把终端设备当做是一种文件
00:57
file.read([size])
00:13
参数用[]括起来,表示它是一个可选参数。不填写也没问题
00:29
file.readline([size]) 。读取整行,包括回车换行符
00:14
file.readlines([sizeint]) 读取所有行并返回列表,若给定 sizeint 大于 0,返回总和大约为sizeint字节的行
00:26
file.seek(offset[, whence]) 移动文件读取指针到指定位置
00:11
移动文件指针可以从多个位置开始
00:37
file.tell() 返回文件当前位置
00:07
file.truncate([size]) 从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断
00:29
file.truncate([size]) 方法介绍
00:30
file.write(str) 将字符串写入文件,返回的是写入的字符长度
00:11
file.writelines(sequence) 向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符
00:15
file 方法总结
00:47
Python 3 OS 文件和目录方法
00:23
os 模块提供了非常丰富的方法用来处理文件和目录
00:19
import os 导入 os 模块
00:17
os 模块的帮助信息
01:11
菜鸟网 上 os 模块相关介绍信息
00:26
打开 菜鸟网 学习 Python 3 编程
01:12
通过网站学习 Python 3 非常高效便捷
00:30
菜鸟网的目录和内容结构
01:00
菜鸟网还可以学习其他的重要编程语言
01:17
Python3 OS 文件 和 目录方法 - 菜鸟网使用方法
00:22
os 模块有多达 66 个方法可以学习使用
00:29
逐个介绍 os 文件和目录方法
00:30
os.access(path, mode) 检验权限模式
00:34
os.access(path, mode) 参数的含义
00:49
os.chdir(path) 改变当前工作目录
00:39
os.chdir() 方法用于改变当前工作目录到指定的路径
00:25
os.chflags(path, flags) 设置路径的标记为数字标记
00:11
os.chflags() 方法用于设置路径的标记为数字标记。多个标记可以使用 OR 来组合起来。只支持在 Unix 下使用
00:39
os.chmod(path, mode) 更改权限
00:12
os.chmod() 方法用于更改文件或目录的权限。Unix 系统可用
00:34
os.chown(path, uid, gid) 更改文件所有者
00:11
os.chown() 方法用于更改文件所有者,如果不修改可以设置为 -1, 你需要超级用户权限来执行权限修改操作。只支持在 Unix 下使用
00:35
os.chroot(path) 改变当前进程的根目录
00:11
os.chroot() 方法用于更改当前进程的根目录为指定的目录,使用该函数需要管理员权限。UNIX 有效
00:22
os.close(fd) 关闭文件描述符 fd
00:13
os.close() 方法用于关闭指定的文件描述符 fd
00:28
前面是 os 模块的简单介绍。需要使用时可以具体查询某个方法的使用方式
00:50
Python 3 错误和异常
00:23
作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息
00:54
Python 有两种错误很容易辨认:语法错误 和 异常
00:20
Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常
00:18
Python 的语法错误或者称之为解析错,是初学者经常碰到的
00:26
while True print('Hello world') 错误再哪里?
00:16
这个例子中,函数 print() 被检查到有错误,是它前面缺少了一个冒号
00:30
语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头
00:17
while True 冒号 print('Hello world')
00:34
即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误
00:33
运行期检测到的错误被称为异常
00:12
大多数的异常都不会被程序处理,都以错误信息的形式展现在这里
00:11
大多数的 异常 都不会被程序处理,都以错误信息的 形式展现在这里
00:21
除数是变量或者随机数,某次取值刚好是零,而触发异常
00:45
spam 未定义,触发异常
00:17
没有通过赋值生成变量就直接使用会触发异常
00:33
没有导入 math 库而触发异常
00:37
没有导入指定模块而调用模块中的方法、常量就会触发异常
00:29
int 不能与 str 相加,触发异常
00:12
字符串可以相加,整数可以相加,但字符串和整数不能相加
00:19
字符串除以整数,触发异常
00:36
文件对象的write()方法,尝试写入列表数据出现异常
01:30
异常种类实际上非常繁多
00:33
异常以不同的类型出现,这些类型都作为信息的一部分打印出来
00:15
例子中的类型有 ZeroDivisionError,NameError 和 TypeError
00:12
同一个 NameError 可能有多种出错的原因
00:32
同一个 TypeError 也出现在多个不同的地方
00:33
错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息
00:18
错误信息显示结果
00:39
使用 Control-C 或者操作系统提供的方法。用户中断的信息会引发一个 KeyboardInterrupt 异常
00:37
无限循环用 KeyboardInterrupt 抛出异常而终止
00:24
无限循环,异常处理程序分析
00:31
深度分析,无限循环,数据输入,异常处理程序
00:37
运行无限循环,待用户输入数据的程序
00:31
分析异常产生的原因。我们认为是 int() 转换时产生了异常
00:53
转换字母 a 时出现错误
00:29
while 无限循环,不断检测输入数据的情况。出现异常之后处理异常,直到输入结果正确为止
00:49
try...except 语句工作方式
00:12
首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)
00:22
try 后面有冒号,和 while,if 等语句类似
00:32
如果没有异常发生,忽略 except 子句,try 子句执行后结束
00:26
try...except 的运行机制同if...else非常类似
00:32
如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略
00:26
如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行
00:49
如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中
00:26
一个 try 语句可能包含多个 except 子句,分别来处理不同的特定的异常
00:28
最多只有一个分支会被执行
00:21
处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常
00:26
一个 except 子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组
00:19
except (RuntimeError, TypeError, NameError)
00:20
except 的条件可以是单条件,也可以是多个条件混合
00:49
最后一个except子句可以忽略异常的名称,它将被当作通配符使用
00:10
系统允许 except 不带任何异常类型,可以匹配任何类型的异常
00:26
你可以使用这种方法打印一个错误信息,然后再次把异常抛出
00:20
try 子句中打开文件,读取一行
00:51
except OSError as err。针对 OSError 进行处理
00:43
except ValueError 数据转换出错,在这里处理
00:20
其他未知的错误,再输出出来
00:37
读取文件内容并转换。异常处理程序完整解析
00:40
try...except...else
00:14
try...except 语句还有一个可选的 else 子句
00:31
如果使用这个子句,那么必须放在所有的 except 子句之后
00:12
else 子句将在 try 子句没有发生任何异常的时候执行
00:26
以下实例在 try 语句中判断文件是否可以打开
00:11
如果打开文件时正常的没有发生异常则执行 else 部分的语句,读取文件内容
00:19
使用 else 子句比把所有的语句都放在 try 子句里面要好
00:41
这样可以避免一些意想不到,而 except 又无法捕获的异常
00:27
try 子句:读取一个不存在的文件
00:14
如果文件无法打开做抛出操作系统错误
00:14
如果文件存在,则跳过异常处理直接进入 else 子句
00:19
包含 else 的 try...except 程序
00:22
运行包含 else 的 try...except结构
00:17
生成文本文件,准备读取
00:33
生成文件之后,成功打开文件,进入else子句
00:19
异常处理并不仅仅处理那些直接发生在 try 子句中的异常
00:29
还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常
00:34
调用关系非常清晰,层层向上抛出异常
00:30
定义了一个包含除零异常的函数
00:20
def this_fails()
00:23
try 子句中调用了包含有错误的语句
00:22
except ZeroDivisionError as err
00:27
as 用于缩写模块或错误的名称
00:24
成功处理了 Handling run-time error - division by zero
00:24
try-finally 语句
00:13
try-finally 语句无论是否发生异常都将执行最后的代码
00:18
finally 和 else 的区别
00:19
runoob() try 子句中的这个函数没有定义
00:21
except AssertionError as error
00:15
else 中包含异常处理程序
00:57
完整的 try...finally 程序分析
00:48
定义 def runoob() 函数
00:21
有了函数,进入了else但是还是没有文件
00:38
函数问题解决了,就是文件的问题
00:16
生成待读取文件成功
00:13
有了函数和文件,程序能够正常运行。finally 子句总会运行
00:24
完整的 try...except...finally 结构
00:42
抛出异常
00:27
用户主动抛出异常,而不是系统遇到错误而抛出异常
00:36
Python 使用 raise 语句抛出一个指定的异常
00:11
raise 是函数,还是保留字,还是系统变量?
00:18
加载 keyword 模块,展示 kwlist。raise 是关键字
00:42
raise 果然是关键字
00:24
raise 主动抛出指定异常。也可以不指定
00:36
raise [Exception [, args [, traceback]]] 基本语法
00:13
用户主动设置并抛出异常
00:29
raise 唯一的一个参数指定了要被抛出的异常
00:11
它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)
00:14
Exception() 似乎是一个函数
00:13
Exception() 似乎是一个构造函数,用于生成新的异常
00:42
Exception 还有很多子类,错误信息
00:27
有时我们只是抛出了一个异常,并不想去处理它
00:10
那么一个简单的 raise 语句就可以再次把它抛出
00:14
raise NameError('HiThere')
00:31
except NameError 处理异常的子句
00:22
raise NameError('HiThere')。实际处理异常后的结果
00:38
try...except...else...finally 同 if...else...作对比
01:03
try...else...结构可以看作是特殊的if...else...分支结构
00:31
用户自定义异常
00:31
你可以通过创建一个新的异常类来拥有自己的异常
00:12
异常类继承自 Exception 类,可以直接继承或者间接继承
00:14
自定义异常为什么很重要
00:48
在这个例子中,类 Exception 默认的 __init__() 被覆盖
00:12
class MyError(Exception)
00:22
def __init__(self, value)
00:19
def __str__(self)
00:19
加载 MyError 类之后没有看到相关信息
00:53
raise MyError(2※2)
00:38
except MyError as e
00:19
运行程序抛出自定义异常
00:26
MyError 类果然加载到系统中了
00:38
后期会详细介绍自定义类的编写方法
00:27
创建一个模块可能抛出多种不同的异常
00:42
一种通常的做法是为这个包建立一个基础异常类
00:19
然后基于这个基础类为不同的错误情况创建不同的子类
00:15
大多数的异常的名字都以 Error 结尾,就跟标准的异常命名一样
00:11
class Error(Exception)
00:20
Base class for exceptions in this module
00:21
class InputError(Error)
00:17
Exception raised for errors in the input
00:14
expression, message 的含义
00:40
__init__(self, expression, message)
00:34
class TransitionError(Error)
00:28
Raised when an operation attempts a state transition that's not
00:20
状态转换失败会抛出这种异常
00:22
previous, next, message
00:21
__init__(self, previous, next, message)
00:29
定义清理行为
00:31
try 语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为
00:26
不管 try 子句里面有没有发生异常,finally 子句都会执行
00:10
raise KeyboardInterrupt
00:16
print('Goodbye, world!')
00:12
分析程序,运行最终结果
00:49
如果一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出
00:30
而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后 被抛出
00:51
except 拦截异常的方式有很多
00:31
def divide(x, y)
00:27
try 子句,浮点数除法
00:24
except ZeroDivisionError 子句
00:31
无异常就进入 else 子句
00:17
无论是否有异常都会执行 finally 子句的内容
00:11
加载 divide() 函数到内存中
00:22
divide(2,1) 程序正常运行
00:26
有除零错误,触发异常处理程序
00:38
输入错误,程序触发异常,但无法处理,finally 部分运行结束后继续抛出异常
01:00
预定义的清理行为
00:15
一些对象定义了标准的清理行为,无论系统是否成功的使用了它
00:16
一旦不需要它了,那么这个标准的清理行为就会执行
00:19
下面这个例子展示了尝试打开一个文件,然后把内容打印到屏幕上
00:11
打开文件遍历每一行内容
00:36
finally 无论如何都会执行
00:11
返回文件未找到错误
00:16
我们曾经在该目录下生成过文本文件。所以换文件名即可
00:15
读取文件获得数据信息
00:16
修改系统目录为当前程序目录
00:20
读取文件出现解码错误。准备重新生成文件写入文本数据
00:56
通过 Spyder 系统查找功能找到早期的读写文件代码
00:40
代码分析-打开文件并写入一些内容
00:22
生成文件并写入数据成功
00:22
尝试读取文件获得成功
00:25
查找文件回到测试代码段
00:13
打开文件,通过枚举文件对象的方式输出文件内容
00:20
关键词 with 语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法
00:14
with open('tmp.txt') as f 代码分析
00:39
with 语句结束部分要用冒号开始新的语句
00:18
with 语句同 def,class 等语句类似
00:34
with 内部有两层缩进
00:28
以上这段代码执行完毕后,就算在处理过程中出问题了,文件 f 总是会关闭
00:12
Python assert(断言)用于判断一个表达式
00:15
在表达式条件为 false 的时候触发异常
00:20
未必是逻辑表达式,算数表达式计算结果为 0 也会触发异常
00:26
assert 1-1 触发了异常
00:15
assert 0 触发异常
00:16
assert False 触发异常
00:13
assert True 不会触发任何异常
00:13
assert 3 大于 5。返回值是False触发异常
00:15
断言可以在条件不满足程序运行的情况下直接返回错误
00:15
而不必等待程序运行后出现崩溃的情况
00:15
例如我们的代码只能在 Linux 系统下运行,可以先判断当前系统是否符合条件
00:19
assert 发音注意事项
00:15
assert expression
00:16
if not expression
00:29
assert 后面也可以紧跟参数
00:15
assert expression [, arguments]
00:08
raise AssertionError(arguments)
00:21
给用户一个直接触发异常的方法
00:22
条件为 true 正常执行
00:09
assert 1==1
00:09
assert 1==2
00:18
判断当前系统是否为 Linux,如果不满足条件则直接触发异常,不必执行接下来的代码
00:13
判断当前系统是否为 Linux 系统
00:26
sys.platform 查看当前系统的类型
00:22
assert ('linux' in sys.platform)
00:30
Python 3 面向对象编程
00:25
后面这些内容就是这个系列最后的部分
00:16
Python 从设计之初就已经是一门面向对象的语言
00:22
正因为如此,在 Python 中创建一个类和对象是很容易的
00:12
class 可以声明一个类
00:16
本章节我们将详细介绍 Python 的面向对象编程
00:20
你可能需要先了解一些面向对象语言的一些基本特征
00:17
在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程
00:15
接下来我们先来简单的了解下面向对象的一些基本特征
00:16
面向对象技术简介
00:20
类(Class):用来描述具有相同的属性和方法的对象的集合
00:12
它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
00:16
用 字符串 类和对象做案例分析
00:38
方法:类中定义的函数
00:26
字符串、列表等对象中有很多、很多的方法
00:32
类变量:类变量在整个实例化的对象中是公用的
00:19
类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用
00:13
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据
00:21
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写
00:12
这个过程叫方法的覆盖(override),也称为方法的重写
00:08
异常处理中用过:方法重写
00:35
局部变量:定义在方法中的变量,只作用于当前实例的类
00:21
局部变量 : 定义在方法中的变量, 只作用于 当前实例的类
00:16
实例变量就是一个用 self 修饰的变量
00:10
在写异常处理类时多次遇到过self修饰的变量
00:15
实例变量 就是一个用 self 修饰的 变量
00:20
以狗作为例子分析继承、基类等概念
00:44
继承也允许把一个派生类的对象作为一个基类对象对待
00:16
例如,有这样一个设计:一个 Dog 类型的对象派生自 Animal 类
00:19
这是模拟 是一个(is-a) 关系(例图,Dog 是一个Animal)
00:20
可以在菜鸟网查看相关的图例
00:22
实例化:创建一个类的实例,类的具体对象
00:11
用狗的例子讲实例化
00:39
用字符串和列表将实例化的案例
00:40
实例化 : 创建一个类的实例, 类的具体对象
00:17
以列表、元组、字典对象举例
00:30
以文件对象举例说明对象
00:39
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制
00:23
Python 中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类
00:15
派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法
00:49
对象可以包含任意数量和类型的数据
00:23
class ClassName 类的定义
00:35
类和函数的区别
00:23
类实例化后,可以使用其属性
00:19
用字符串和列表举例,什么是实例化
00:40
实际上,创建一个类之后,可以通过类名访问其属性
00:14
math.pi 通过类名访问属性
00:29
类对象支持两种操作:属性引用和实例化
00:16
属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name
00:20
类实例化一个对象之后可以直接引用其中的属性
00:29
类对象创建后,类命名空间中所有的命名都是有效属性名
00:23
创建了一个新的类实例并将该对象赋给局部变量 x,x 为空的对象
00:15
MyClass 类的完整定义
00:42
MyClass 类加载到当前运行环境中
00:26
dir(MyClass) 查看类内部的名称
00:44
help(MyClass) 查询帮助信息
01:00
MyClass.i 通过类名来访问属性
00:38
通过类名访问方法
00:32
实例化一个类
00:30
通过变量管理器查看实例化以后的对象
00:34
通过对象管理器查看对象中的方法和属性
01:25
通过对象访问类的属性
00:23
x.f() 通过对象访问类中的方法
00:14
类和对象之间的关系
00:58
类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用
00:17
def __init__(self)
00:30
类定义了 __init__() 方法,类的实例化操作会自动调用 __init__() 方法
00:38
如下实例化类 MyClass,对应的 __init__() 方法就会被调用
00:11
如下 实例化类 MyClass,对应的 __init__() 方法就会被调用
00:13
__init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上
00:31
class Complex 定义一个复数类,并编写构造方法的内容
00:33
将 Complex 类加载到当前运行环境中
00:21
给定参数生成 Complex 对象
00:27
通过对象查看器,查看Complex对象的内容
00:35
print(x.r, x.i) 访问对象的属性
00:55
在 IDE 中类的定义、函数定义等部分可以收缩和展开。方便阅读代码
00:59
self 代表类的实例,而非类
00:22
类的方法与普通的函数只有一个特别的区别:它们必须有一个额外的、排第一的参数名称, 按照惯例它的名称是 self
00:28
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址
00:14
而 self.class 则指向类
00:09
class Test 定义一个类 Test
00:38
加载 Test 到当前运行环境中
00:41
生成 Test 对象,并调用类的方法 prt()
00:56
self 不是 Python 关键字,我们把他换成 runoob 也是可以正常执行的
00:23
不使用 self 同样可以定义一个类的方法
00:23
成功加载新的类,调用 prt() 方法
00:29
t1 和 t2 不是同一个类
00:21
在类的内部,使用 def 关键字来定义一个方法
00:13
与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例
00:27
class people。定义基本属性
00:27
定义私有属性,私有属性在类外部无法直接进行访问
00:23
定义构造方法,初始化数据
00:49
def speak(self) 定义一个类方法
00:47
加载 people 类成功
00:28
通过类名访问类的属性成功
01:07
客服
顶部
赛事库 课堂 2021拜年纪