first commit

This commit is contained in:
2025-08-27 14:39:37 +08:00
commit 81ebee9cf3
97 changed files with 14191 additions and 0 deletions

View File

@@ -0,0 +1,913 @@
# Python基础
## 安装python
## 运行python代码
在硬盘创建文件 t1.py并且使用 PyCharm 打开,输入以下代码
```python
print('Hello World!')
```
然后右键运行
![image](01.python基础/1553917000771-909b5d59-8d4a-4e57-9dfe-95f0ba3a12ee.png)
运行结果
```
C:\Users\Aaron\AppData\Local\Programs\Python\Python35\python.exe C:/Users/Aaron/Desktop/py/t1.py
Hello World!
Process finished with exit code 0
```
## 注释
当行注释:# 被注释内容
多行注释:''' 被注释内容 ''',或者 """ 被注释内容 """
## 变量
变量是什么? 变量:把程序运行的中间结果临时的存在内存里,以便后续的代码调用。
## 声明变量
```python
a = "Hello World!"
print(a)
```
## 变量定义的规则
- 变量名只能是 字母、数字或下划线的任意组合
- 变量名的第一个字符不能是数字
- 以下关键字不能声明为变量名
- ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']
- 变量的定义要具有可描述性。
## 变量的赋值
```python
a = "变量1"
b = "变量2"
```
![image](01.python基础/1553917013597-9d6b5e70-3c79-4042-81a1-2459eca7cae8.png)
```python
a = "变量1"
b = a
```
![image](01.python基础/1553917020154-5c92c78b-e289-42a7-8b42-d6f563ed4dad.png)
## 常量
常量即指不变的量,如 pi 3.141592653..., 或在程序运行过程中不会改变的量。
## 程序交互
```python
name = input("请输入姓名:")
print(name)
```
执行脚本就会发现,程序会等待你输入姓名后再往下继续走。
```python
请输入姓名Aaron
Aaron
```
## 基础数据类型
### 整数型int
在 32 位机器上,整数的位数为 32 位,取值范围为 -2**312**31-1即 -21474836482147483647
在 64 位系统上,整数的位数为 64 位,取值范围为 -2**632**63-1即 -92233720368547758089223372036854775807
注意:在 Python3 里不再有 long 类型了,全都是 int
```python
a = 2**64
print(type(a)) #type()是查看数据类型的方法
b = 2**60
print(type(b))
```
运行结果
```python
<class 'int'>
<class 'int'>
```
## 字符串类型str
在 Python 中, 加了引号的字符都被认为是字符串!
```python
a = "Eagle's Lab"
b = '''
欢迎大家来到英格科技!
今天我们学习python!'''
print(a,b)
```
运行结果
```python
Eagle's Lab
欢迎大家来到英格科技!
今天我们学习python!
```
字符串拼接
```python
a = 'eagle '
b = 'welcome '
print(b + a,'*' * 3,a * 3)
```
运行结果
```python
welcome eagle *** eagle eagle eagle
```
## 布尔值True, False)
布尔类型很简单,就两个值 ,一个 True(真),一个 False(假), 主要用记逻辑判断
```python
a = 3
b = 5
print(a < b, a > b , a != b)
```
运行结果
```
True False True
```
## 格式化输出
```python
name = input("姓名:")
age = input("年龄:")
job = input("工作:")
info = '''
----------- info of %s -----------
姓名:%s
年龄:%s
工作:%s
''' % (name,name,age,job)
print(info)
```
运行结果
```
姓名Aaron
年龄18
工作Teacher
----------- info of Aaron -----------
姓名Aaron
年龄18
工作Teacher
```
## 基本运算符
算数运算
| 运算符 | 描述 | 实例 |
| ------ | -------------- | ----------------- |
| + | 加 | a+b 输出结果30 |
| - | 减 | a-b 输出结果-10 |
| * | 乘 | a*b 输出结果200 |
| / | 除 | b/a 输出结果2 |
| % | 取模 得到余数 | b%a 输出结果0 |
| ** | 幂 | a**2 输出结果100 |
| // | 取整 | 9//2 输出结果4 |
比较运算
| 运算符 | 描述 | 实例 |
| ------ | -------- | ----------------- |
| == | 等于 | a == b 返回False |
| != | 不等于 | a != b 返回True |
| <> | 不等于 | a <> b 返回True |
| > | 大于 | a > b 返回False |
| < | 小于 | a < b 返回True |
| >= | 大于等于 | a >= b 返回False |
| <= | 小于等于 | a <= b 返回True |
赋值运算
| 运算符 | 描述 | 实例 |
| ------ | ---------------- | --------- |
| = | 赋值运算符 | c = a + b |
| += | 加法赋值运算符 | c += a |
| -= | 加法赋值运算符 | c -= a |
| *= | 乘法赋值运算符 | c *= a |
| /= | 除法赋值运算符 | c /= a |
| %= | 取模赋值运算符 | c %= a |
| **= | 幂赋值运算符 | c **= a |
| //= | 取整除赋值运算符 | c //= a |
逻辑运算
| 运算符 | 描述 | 实例 |
| ------ | ---- | ------------ |
| and | 与 | a and b |
| or | 或 | a or b |
| not | 非 | not(a and b) |
在没有 () 的情况下 not 优先级高于 andand 优先级高于 or即优先级关系为()>not>and>or同一优先级从左往右计算。
x or y , x 为真,值就是 xx 为假,值是 y x and y, x 为真,值是 y,x 为假,值是 x。
成员运算
| 运算符 | 描述 | 实例 |
| ------ | ------------------------------------------------- | ---------- |
| in | 如果在指定的序列中找到值返回True,否则返回False | x in y |
| not in | 如果在指定的序列中没有找到返回True否则返回False | x not in y |
```python
print('a' in 'abcd')
print('y' not in 'xyzasd')
```
运行结果
```
True
False
```
**Python 运算符优先级**
以下表格列出了从最高到最低优先级的所有运算符:
| 运算符 | 描述 |
| ------------------------ | ------------------------------------------------------ |
| ** | 指数 (最高优先级) |
| ~ + - | 按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@) |
| * / % // | 乘,除,取模和取整除 |
| + - | 加法减法 |
| >> << | 右移,左移运算符 |
| & | 位 'AND' |
| ^ | 位运算符 |
| <= < > >= | 比较运算符 |
| <> == != | 等于运算符 |
| = %= /= //= -= += *= **= | 赋值运算符 |
| is is not | 身份运算符 |
| in not in | 成员运算符 |
| not and or | 逻辑运算符 |
## 流程控制之 --if
单分支
```python
if 条件:
满足条件后要执行的代码
```
双分支
```python
"""
if 条件:
满足条件执行代码
else:
if条件不满足就走这段
"""
age = 48
if age > 50 :
print("尚能饭否")
else:
print("廉颇老矣")
```
运行结果
```
廉颇老矣
```
if...else ... 可以有多个分支条件
```python
if 条件:
满足条件执行代码
elif 条件:
上面的条件不满足就走这个
elif 条件:
上面的条件不满足就走这个
elif 条件:
上面的条件不满足就走这个
else:
上面所有的条件不满足就走这段
```
## 流程控制之 --while
基本循环
```python
while 条件:
循环体
```
如果条件为真,那么循环体则执行
如果条件为假,那么循环体不执行
循环中止语句
break 用于完全结束一个循环,跳出循环体执行循环后面的语句
continue 和 break 有点类似,区别在于 continue 只是终止本次循环接着还执行后面的循环break 则完全终止循环
```python
print('猜数字游戏开始')
num = 54
while True:
guess = int(input("您猜数字是什么?(输入0-100的数字)"))
if guess < num:
print("您猜小了")
continue
elif guess > num:
print("您猜大了")
continue
break
print("您猜对了!")
```
运行结果
```
猜数字游戏开始
您猜数字是什么?(输入0-100的数字)50
您猜小了
您猜数字是什么?(输入0-100的数字)60
您猜大了
您猜数字是什么?(输入0-100的数字)54
您猜对了!
```
while ... else ..
while 后面的 else 作用是指,当 while 循环正常执行完,中间没有被 break 中止的话,就会执行 else 后面的语句
## 基础数据类型
### 数字 (int)
```python
v = 11
data = v.bit_length() #当十进制用二进制表示时,最少使用的位数
print(data)
```
运行结果
```
4
```
### 布尔值 ()bool
布尔值就两种TrueFalse。就是反应条件的正确与否。
真 1 True。
假 0 False。
### 字符串 str
#### 字符串的索引与切片
```python
a = 'ABCDEFGHIJK'
print(a[0])
print(a[3])
print(a[5])
print(a[7])
a = 'ABCDEFGHIJK'
print(a[0:3])
print(a[2:5])
print(a[0:]) #默认到最后
print(a[0:-1]) # -1 是列表中最后一个元素的索引但是要满足顾头不顾腚的原则所以取不到K元素
print(a[0:5:2]) #加步长
print(a[5:0:-2]) #反向加步长
```
运行结果
```
A
D
F
H
ABC
CDE
ABCDEFGHIJK
ABCDEFGHIJ
ACE
FDB
```
#### 字符串常用方法
```python
words = "beautiful is better than ugly."
print(words.capitalize()) #首字母大写
print(words.swapcase()) #大小写翻转
print(words.title()) #每个单词的首字母大写
## 内容居中,总长度,空白处填充
a = "test"
ret = a.center(20,"*")
print(ret)
## 数字符串中的元素出现的个数
ret = words.count("e",0,30)
print(ret)
a = "aisdjioadoiqwd12313assdj"
## startswith 判断是否以...开头
## endswith 判断是否以...结尾
print(a.startswith("a"))
print(a.endswith("j"))
print(a.startswith('sdj',2,5))
print(a.endswith('ado',7,10))
## 寻找字符串中的元素是否存在
print(a.find('sdj',1,10)) # 返回的找到的元素的索引,如果找不到返回-1
print(a.index('sdj',1,10)) # 返回的找到的元素的索引,找不到报错。
## split 以什么分割,最终形成一个列表此列表不含有这个分割的元素。
ret = words.split(' ')
print(ret)
ret = words.rsplit(' ',2)
print(ret)
## format的三种玩法 格式化输出
print('{} {} {}'.format('aaron',18,'teacher'))
print('{1} {0} {1}'.format('aaron',18,'teacher'))
print('{name} {age} {job}'.format(job='teacher',name='aaron',age=18))
## strip
a = '****asdasdasd********'
print(a.strip('*'))
print(a.lstrip('*'))
print(a.rstrip('*'))
## replace
print(words.replace('e','a',2))
print(words.isalnum()) #字符串由字母或数字组成
print(words.isalpha()) #字符串只由字母组成
print(words.isdigit()) #字符串只由数字组成
```
### 元祖 tuple
元组被称为只读列表,即数据可以被查询,但不能被修改。
### 列表 list
列表相比于字符串不仅可以储存不同的数据类型而且可以储存大量数据32 位 python 的限制是 536870912 个元素,64 位 python 的限制是 1152921504606846975 个元素。而且列表是有序的,有索引值,可切片,方便取值。
#### 增
```python
li = [1,'a',2,'d',4]
li.insert(0,22) # 按照索引去增加
print(li)
li.append('ddd') # 增加到最后
print(li)
li.extend(['q,a,w']) # 迭代的去增
print(li)
li.extend(['q,a,w','das']) # 迭代的去增
print(li)
```
运行结果
```
[22, 1, 'a', 2, 'd', 4]
[22, 1, 'a', 2, 'd', 4, 'ddd']
[22, 1, 'a', 2, 'd', 4, 'ddd', 'q,a,w']
[22, 1, 'a', 2, 'd', 4, 'ddd', 'q,a,w', 'q,a,w', 'das']
```
#### 删
```python
li = [1,'a',2,'d',4,5,'f']
a = li.pop(1) # 按照位置去删除,有返回值
print(a)
del li[1:3] # 按照位置去删除,也可切片删除没有返回值。
print(li)
li.remove('f')
print(li)
li.clear()
print(li)
```
运行结果
```
a
[1, 4, 5, 'f']
[1, 4, 5]
[]
```
#### 改
```python
li = [1,'a',2,'d',4,5,'f']
li[1] = 'aaa'
print(li)
li[2:3] = [3,'e']
print (li)
```
运行结果
```
[1, 'aaa', 2, 'd', 4, 5, 'f']
[1, 'aaa', 3, 'e', 'd', 4, 5, 'f']
```
#### 查
切片去查,或者循环去查。
#### 其他操作
```python
li = [1,2,4,5,4,2,4]
print (li.count(4)) # 统计某个元素在列表中出现的次数
print (li.index(2)) # 用于从列表中找出某个值第一个匹配项的索引位置
li.sort() # 用于在原位置对列表进行排序
print (li)
li.reverse() # 将列表中的元素反向存放
print (li)
```
运行结果
```
3
1
[1, 2, 2, 4, 4, 4, 5]
[5, 4, 4, 4, 2, 2, 1]
```
### 字典dict
字典是python中唯一的映射类型采用键值对key-value的形式存储数据。python对key进行哈希函数运算根据计算的结果决定value的存储地址所以字典是无序存储的且key必须是可哈希的。可哈希表示key必须是不可变类型数字、字符串、元组。
#### 增
```python
dic = {"age":18, "name":"aaron"}
dic['li'] = ["a","b","c"]
print(dic)
dic.setdefault('k','v')
## 在字典中添加键值对如果只有键那对应的值是none,但是如果原字典中存在设置的键值对,则他不会更改或者覆盖。
print(dic)
dic.setdefault('k','v1')
print(dic)
```
#### 删
```python
dic = {"age":18, "name":"aaron"}
dic_pop = dic.pop('age')
## pop根据key删除键值对并返回对应的值如果没有key则返回默认返回值
print(dic_pop)
dic_pop = dic.pop('sex','查无此项')
print(dic_pop)
dic['age'] = 18
print(dic)
del dic['name']
print(dic)
dic['name'] = 'demo'
dic_pop = dic.popitem()
## 随机删除字典中的某个键值对,将删除的键值对以元祖的形式返回
print(dic_pop)
dic_clear = dic.clear()
## 清空字典
print(dic,dic_clear)
```
#### 改
```python
dic = {"age":18, "name":"aaron", 'sex':'male'}
dic2 = {"age":30, "name":'demo'}
dic2.update(dic)
## 将dic所有的键值对覆盖添加相同的覆盖没有的添加到dic2中
print(dic2)
dic2['age'] = 30
print(dic2)
```
#### 查
```python
dic = {"age":18, "name":"aaron", 'sex':'male'}
value = dic['name']
## 没有会报错
print(value)
value = dic.get('abc','查无此项')
print(value)
```
#### 其他操作
```python
dic = {"age":18, "name":"aaron", 'sex':'male'}
for i in dic.items():
# 将键和值作为元祖列出
print(i)
for key,value in dic.items():
print(key,value)
for i in dic:
# 只是迭代键
print(i)
keys = dic.keys()
print(keys,type(keys))
value = dic.values()
print(value,type(value))
```
### 集合set
集合是无序的,不重复的数据集合,它里面的元素是可哈希的(不可变类型),但是集合本身是不可哈希(所以集合做不了字典的键)的。以下是集合最重要的两点:
- 去重,把一个列表变成集合,就自动去重了。
- 关系测试,测试两组数据之前的交集、差集、并集等关系。
#### 创建集合
```python
set1 = set({1,2,'barry'})
set2 = {1,2,'barry'}
print(set1,set2)
```
#### 集合的增
```python
set1 = {'abc','def',123,'asdas'}
set1.add('qwer')
print(set1)
set1.update('A')
#update迭代着增加
print(set1)
set1.update('哈哈哈')
print(set1)
set1.update([1,2,3])
print(set1)
```
#### 集合的删
```python
set1 = {'abc','def',123,'asdas'}
set1.remove('abc')
print(set1)
set1.pop()
## 随机删除一个数
print(set1)
set1.clear()
## 清空合集
print(set1)
del set1
## 删除合集
print(set1)
```
#### 集合的其他操作
###### 交集(& 或者 intersection
```python
set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}
print(set1 & set2)
print(set1.intersection(set2))
## 列出两个集合中共同拥有的项
```
##### 并集(|或者 union
```python
set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}
print(set1 | set2)
print(set2.union(set1))
## 列出两个集合中所有的项
```
##### 差集(- 或者 difference
```python
set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}
print(set1 - set2)
print(set1.difference(set2))
## 在set1中删除set2中有的项
```
##### 反交集 ^ 或者 symmetric_difference
```python
set1 = {1,2,3,4,5}
set2 = {3,4,5,6,7}
print(set1 ^ set2)
print(set1.symmetric_difference(set2))
## 显示set1和set2不共存的项
```
##### 子集与超集
```python
set1 = {1,2,3}
set2 = {1,2,3,4,5,6}
print(set1 < set2)
print(set1.issubset(set2)) # 这两个相同都是说明set1是set2子集。
print(set2 > set1)
print(set2.issuperset(set1)) # 这两个相同都是说明set2是set1超集
```
##### frozenset不可变集合让集合变成不可变类型
```python
set1 = {1,2,3,4,5,6}
s = frozenset(set1)
print(s,type(s))
s.add(7) # 不可以修改,会报错
```
## 基础数据类型的总结
### 按存储空间的占用分(从低到高)
1. 数字
2. 字符串
3. 集合:无序,即无序存索引相关信息
4. 元组:有序,需要存索引相关信息,不可变
5. 列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
6. 字典无序需要存key与value映射的相关信息可变需要处理数据的增删改
### 按存值个数区分
| 标量/原子类型 | 数字,字符串 |
| -------------- | ---------------- |
| 容器类型 | 列表,元组,字典 |
### 按可变不可变区分
| 可变 | 列表,字典 |
| ------ | -------------------------- |
| 不可变 | 数字,字符串,元组,布尔值 |
### 按访问顺序区分
| 直接访问 | 数字 |
| --------------------- | ------------------ |
| 顺序访问(序列类型) | 字符串,列表,元组 |
| key值访问映射类型 | 字典 |
## 其他forenumeraterange
for循环用户按照顺序循环可迭代对象的内容。
```python
s = '先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。'
for i in s:
print(i)
li = ['甲','乙','丙','丁']
for i in li:
print(i)
dic = {'a':1,'b':2,'c':3}
for k,v in dic.items():
print(k,v)
```
enumerate枚举对于一个可迭代的iterable/可遍历的对象如列表、字符串enumerate将其组成一个索引序列利用它可以同时获得索引和值。
```python
li = ['甲','乙','丙','丁']
for i in li:
print(i)
for i in enumerate(li):
print(i)
for index,value in enumerate(li):
print(index,value)
for index,value in enumerate(li,100): #从哪个数字开始索引
print(index,value)
```
range指定范围生成指定数字。
```python
for i in range(1,10):
print(i)
for i in range(1,10,2): # 步长
print(i)
for i in range(10,1,-2): # 反向步长
print(i)
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,321 @@
# Python文件操作
## 文件操作基本流程
```python
#1. 打开文件,得到文件句柄并赋值给一个变量
f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r
#2. 通过句柄对文件进行操作
data=f.read()
#3. 关闭文件
f.close()
```
打开一个文件包含两部分资源:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
```python
f.close()
# 回收操作系统级打开的文件
def f
# 回收应用程序级的变量
```
在操作完毕文件后一定要记住f.close(),推荐操作方式使用with关键字来帮我们管理上下文
```python
with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
data=read_f.read()
write_f.write(data)
```
## 文件编码
f=open(...)是由操作系统打开文件那么如果我们没有为open指定编码那么打开文件的默认编码很明显是操作系统说了算了操作系统会用自己的默认编码去打开文件在windows下是gbk在linux下是utf-8。
```python
f=open('a.txt','r',encoding='utf-8')
```
## 文件的打开模式
### 打开文件的模式
| r | 只读模式【默认模式,文件必须存在,不存在则抛出异常】 |
| ---- | ------------------------------------------------------ |
| w | 只写模式【不可读;不存在则创建;存在则清空内容】 |
| a | 只追加写模式【不可读;不存在则创建;存在则只追加内容】 |
对于非文本文件我们只能使用b模式"b"表示以字节的方式操作而所有文件也都是以字节的形式存储的使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式
rb
wb
ab
以b方式打开时读取到的内容是字节类型写入时也需要提供字节类型不能指定编码
### +’模式(就是增加了一个功能)
| r+ | 读写【可读,可写】 |
| ---- | ------------------ |
| w+ | 写读【可写,可读】 |
| a+ | 写读【可写,可读】 |
| 模式 | 可做操作 | 若文件不存在 | 是否覆盖 |
| ---- | -------- | ------------ | ---------- |
| r | 只能读 | 报错 | - |
| r+ | 可读可写 | 报错 | 是 |
| w | 只能写 | 创建 | 是 |
| w+ | 可读可写 | 创建 | 是 |
| a | 只能写 | 创建 | 否,追加写 |
| a+ | 可读可写 | 创建 | 否,追加写 |
### 以bytes类型操作的读写写读写读模式
| r+b | 读写【可读,可写】 |
| ---- | ------------------ |
| w+b | 写读【可写,可读】 |
| a+b | 写读【可写,可读】 |
## 文件操作方法
### 常用操作方法
read3
1. 文件打开方式为文本模式时代表读取3个字符
2. 文件打开方式为b模式时代表读取3个字节
其余的文件内光标移动都是以字节为单位的如seektelltruncate
注意:
1. seek有三种移动方式012其中1和2必须在b模式下进行但无论哪种模式都是以bytes为单位移动的
2. truncate是截断文件所以文件的打开方式必须可写但是不能用w或w+等方式打开因为那样直接清空文件了所以truncate要在r+或a或a+等模式下测试效果。
### 所有的操作方法
```python
def close(self, *args, **kwargs): # real signature unknown
关闭文件
pass
def fileno(self, *args, **kwargs): # real signature unknown
文件描述符
pass
def flush(self, *args, **kwargs): # real signature unknown
刷新文件内部缓冲区
pass
def isatty(self, *args, **kwargs): # real signature unknown
判断文件是否是同意tty设备
pass
def read(self, *args, **kwargs): # real signature unknown
读取指定字节数据
pass
def readable(self, *args, **kwargs): # real signature unknown
是否可读
pass
def readline(self, *args, **kwargs): # real signature unknown
仅读取一行数据
pass
def seek(self, *args, **kwargs): # real signature unknown
指定文件中指针位置
pass
def seekable(self, *args, **kwargs): # real signature unknown
指针是否可操作
pass
def tell(self, *args, **kwargs): # real signature unknown
获取指针位置
pass
def truncate(self, *args, **kwargs): # real signature unknown
截断数据仅保留指定之前数据
pass
def writable(self, *args, **kwargs): # real signature unknown
是否可写
pass
def write(self, *args, **kwargs): # real signature unknown
写内容
pass
def __getstate__(self, *args, **kwargs): # real signature unknown
pass
def __init__(self, *args, **kwargs): # real signature unknown
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass
```
## 文件的修改
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
方式一将硬盘存放的该文件的内容全部加载到内存在内存中是可以修改的修改完毕后再由内存覆盖到硬盘wordvimnodpad++等编辑器)
```python
import os
with open('a.txt') as read_f,open('a.txt.new','w') as write_f:
data = read_f.read()
data = data.replace('Hello','nihao')
write_f.write(data)
os.remove('a.txt')
os.rename('a.txt.new','a.txt')
```
方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
```python
import os
with open('a.txt') as read_f,open('a.txt.new','w') as write_f:
for line in read_f:
line = line.replace('nihao','Hello')
write_f.write(line)
os.remove('a.txt')
os.rename('a.txt.new','a.txt')
```
## 小测验
文件a.txt内容每一行内容分别为商品名字价钱个数。
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3
通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。
```python
list = []
with open('a.txt','r',encoding='utf-8') as file:
for line in file:
list2 = line.strip().split()
if list2:
dic = {'name':list2[0],'price':list2[1],'amount':list2[2]}
list.append(dic)
continue
print(list)
price = 0
for i in list:
price += int(i['price']) * int(i['amount'])
print(price)
```

View File

@@ -0,0 +1,410 @@
# 认识函数
## 什么是函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
## 函数的定义与调用
```python
def my_len():
s = 'hello world'
length = 0
for i in s:
length = length + 1
print(length)
my_len()
```
```python
定义def 关键词开头空格之后接函数名称和圆括号()最后还有一个":"
   def 是固定的不能变他就是定义函数的关键字
   空格 为了将def关键字和函数名分开必须空(四声)当然你可以空2格3格或者你想空多少都行但正常人还是空1格
   函数名函数名只能包含字符串下划线和数字且不能以数字开头虽然函数名可以随便起但我们给函数起名字还是要尽量简短并能表达函数功能
   括号是必须加的先别问为啥要有括号总之加上括号就对了
注释每一个函数都应该对功能和参数进行相应的说明应该写在函数下面第一行以增强代码的可读性
调用就是 函数名() 要记得加上括号
```
## 函数的返回值
```python
def my_len():
s = 'hello world'
length = 0
for i in s:
length = length + 1
return length
str_len = my_len()
print(str_len)
```
**return关键字的作用**
- return 是一个关键字这个词翻译过来就是“返回”所以我们管写在return后面的值叫“返回值”。
- 不写return的情况下会默认返回一个None
- 一旦遇到return结束整个函数。
- 返回的多个值会被组织成元组被返回,也可以用多个值来接收
```python
def ret_demo():
return 1,2,'a',['hello','world']
ret = ret_demo()
print(ret)
```
## 函数的参数
带参数的函数
```python
def my_len(s):
length = 0
for i in s:
length += 1
return length
ret = my_len('hello world!')
print(ret)
```
实际的要交给函数的内容,简称实参。
在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。
1. 按照位置传值:位置参数
```python
def maxnumber(x,y):
the_max = x if x > y else y
return the_max
ret = maxnumber(10,20)
print(ret)
```
1. 按照关键字传值:关键字参数。
```python
def maxnumber(x,y):
the_max = x if x > y else y
return the_max
ret = maxnumber(y = 10,x = 20)
print(ret)
```
1. 位置、关键字形式混着用:混合传参。
```python
def maxnumber(x,y):
the_max = x if x > y else y
return the_max
ret = maxnumber(10,y = 20)
print(ret)
```
位置参数必须在关键字参数的前面
对于一个形参只能赋值一次
1. 默认参数。
```python
def stu_info(name,age = 18):
print(name,age)
stu_info('aaron')
stu_info('song',50)
```
1. 默认参数是一个可变数据类型
```python
def demo(a,l = []):
l.append(a)
print(l)
demo('abc')
demo('123')
```
1. 动态参数
```python
def demo(*args,**kwargs):
print(args,type(args))
print(kwargs,type(kwargs))
demo('aaron',1,3,[1,3,2,2],{'a':123,'b':321},country='china',b=1)
##动态参数,也叫不定长传参,就是你需要传给函数的参数很多,不定个数,那这种情况下,你就用*args**kwargs接收args是元祖形式接收除去键值对以外的所有参数kwargs接收的只是键值对的参数并保存在字典中。
```
## 命名空间和作用域
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间。
命名空间一共分为三种:
- 全局命名空间
- 局部命名空间
- 内置命名空间
取值顺序:
- 在局部调用:局部命名空间->全局命名空间->内置命名空间
- 在全局调用:全局命名空间->内置命名空间
作用域
- 全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
- 局部作用域:局部名称空间,只能在局部范围内生效
### globals和locals方法
```python
print(globals())
print(locals())
def func():
a = 12
b = 20
print(globals())
print(locals())
func()
```
**global**
1. 声明一个全局变量。
2. 在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
```python
def func():
global a
a = 3
func()
print(a)
count = 1
def search():
global count
count = 2
search()
print(count)
```
对可变数据类型listdictset可以直接引用不用通过global
```python
li = [1,2,3]
dic = {'name':'aaron'}
def change():
li.append(4)
dic['age'] = 18
print(dic)
print(li)
change()
print(dic)
print(li)
```
**nonlocal**
1. 不能修改全局变量。
2. 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
```python
def add_b():
b = 1
def do_global():
b = 10
print(b)
def dd_nolocal():
nonlocal b # 应用了上一层的变量b
b = b + 20
print(b) # 发生了改变
dd_nolocal() # 调用函数导致do_global的命名空间b也改变了
print(b)
do_global()
print(b)
add_b() # 最上面一层没有变化
```
## 函数的嵌套和作用域链
```python
def mymax(x,y):
m = x if x > y else y
return m
def maxx(a,b,c,d):
res1 = mymax(a,b)
res2 = mymax(res1,c)
res3 = mymax(res2,d)
return res3
ret = maxx(23,453,12,-13)
print(ret)
```
```python
def f1():
print("in f1")
def f2():
print("in f2")
f2()
f1()
```
## 函数名的本质
函数名本质上就是函数的内存地址
1. 可以被引用
```python
def func():
print('in func')
f = func
print(f)
f()
```
1. 可以被当作容器类型的元素
```python
def f1():
print('f1')
def f2():
print('f2')
def f3():
print('f3')
l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()
```
1. 可以当作函数的参数和返回值
```python
def f1():
print('f1')
def func(argv):
argv()
return argv
f = func(f1)
f()
```
## 闭包
```python
def func():
name = 'aaron'
def inner():
print(name)
return inner
f = func()
f()
```
内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数
判断闭包函数的方法**closure**
```python
def func():
name = 'aaron'
def inner():
print(name)
print(inner.__closure__)
return inner
f = func()
f()
# 最后运行的结果里面有cell就是闭包
name = 'aaron'
def func():
def inner():
print(name)
print(inner.__closure__)
return inner
f = func()
f()
# 输出结果为None说明不是闭包
```
```python
def wrapper():
money = 1000
def func():
name = 'apple'
def inner():
print(name,money)
return inner
return func
f = wrapper()
i = f()
i()
```
```python
def func(a,b):
def inner(x):
return a*x + b
return inner
func1 = func(4,5)
func2 = func(7,8)
print(func1(5),func2(6))
```
```python
from urllib.request import urlopen
def func():
content = urlopen('http://myip.ipip.net').read()
def get_content():
return content
return get_content
code = func()
content = code()
print(content.decode('utf-8'))
content2 = code()
print(content2.decode('utf-8'))
```

View File

@@ -0,0 +1,175 @@
# 装饰器
## 什么是装饰器
让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
## 装饰器的形成过程
如果我想测试某个函数的执行时间
```python
import time
def func1():
print('in func1')
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
func1 = timer(func1)
func1()
```
但是如果有多个函数我都想让你测试他们的执行时间你每次是不是都得func1 = timer(func1)?这样还是有点麻烦因为这些函数的函数名可能是不相同有func1func2,graph,等等所以更简单的方法python给你提供了那就是语法糖。
```python
import time
def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner
@timer
def func1():
time.sleep(1)
print('in func1')
func1()
```
装饰一个带参数的函数
```python
import time
def timer(func):
def inner(a):
start = time.time()
func(a)
print(time.time() - start)
return inner
@timer
def func1(a):
time.sleep(1)
print(a)
func1('hello world')
```
装饰一个带各种参数的函数
```python
import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
func(args,kwargs)
print(time.time() - start)
return inner
@timer
def func1(*args,**kwargs):
print(args,kwargs)
func1('hello world','abc',123,432)
```
查看函数的相关信息,在加上装饰器后就失效了
```python
def index():
'''这是一条注释信息'''
print('from index')
print(index.__doc__) # 查看函数注释
print(index.__name__) # 查看函数名称
```
导入wraps装饰器
```python
from functools import wraps
def deco(func):
@wraps(func)
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper
@deco
def index():
'''这是一条注释信息'''
print('from index')
print(index.__doc__) # 查看函数注释
print(index.__name__) # 查看函数名称
```
## 开放封闭原则
一句话,软件实体应该是可扩展但是不可修改的。
* 对于扩展是开放的
* 对于修改是封闭的
装饰器完美的遵循了这个开放封闭原则
## 装饰器的主要功能和固定结构
```python
def timer(func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner
# 下面是加上wraps的固定结构
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args,**kwargs)
return func(*args,**kwargs)
return wrapper
```
## 带参数的装饰器
加上一个outer函数可以携带一个flag的值然后控制装饰器是否生效
```python
def outer(flag):
def timer(func):
def inner(*args,**kwargs):
if flag:
print('函数开始执行')
re = func(*args,**kwargs)
if flag:
print('函数执行完毕')
return re
return inner
return timer
@outer(True)
def func():
print('test')
func()
```
## 多个装饰器装饰一个函数
```python
def wrapper1(func):
def inner():
print('第一个装饰器,在程序运行之前')
func()
print('第一个装饰器,在程序运行之后')
return inner
def wrapper2(func):
def inner():
print('第二个装饰器,在程序运行之前')
func()
print('第二个装饰器,在程序运行之后')
return inner
@wrapper1
@wrapper2
def f():
print('Hello')
f()
```

View File

@@ -0,0 +1,177 @@
# 迭代器与生成器
## 迭代器
字符串、列表、元组、字典、集合都可以被for循环说明他们都是可迭代的
```python
from collections import Iterable
l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}
print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable))
```
### 可迭代协议
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单就是内部实现了iter方法。
```python
l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}
print(dir(l))
print(dir(t))
print(dir(d))
print(dir(s))
```
可迭代的内部必须含有一个iter方法。
### 迭代器
```python
l = [1, 2, 3, 4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
```
迭代器遵循迭代器协议必须拥有iter方法和next方法。
for循环能遍历一个可迭代对象他的内部到底进行了什么
将可迭代对象转化成迭代器。(可迭代对象.iter()
内部使用next方法一个一个取值。
加了异常处理功能,取值到底后自动停止。
```python
l = [1, 2, 3, 4]
l_iter = l.__iter__()
while True:
try:
item = l_iter.__next__()
print(item)
except StopIteration:
break
```
### 为什么要有for循环
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法即在遍历之前先调用对象的iter方法将其转换成一个迭代器然后使用迭代器协议去实现循环访问这样所有的对象就都可以通过for循环来遍历了
最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存
## 生成器
### 初识生成器
**Python中提供的生成器**
1. 生成器函数常规函数定义但是使用yield语句而不是return语句返回结果。yield语句一次返回一个结果在每个结果中间挂起函数的状态以便下次重它离开的地方继续执行
2. 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
**生成器Generator**
* 本质:迭代器(所以自带了iter方法和next方法不需要我们去实现)
* 特点:惰性运算,开发者自定义
### 生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值但是yield又不同于returnreturn的执行意味着程序的结束调用生成器函数不会得到返回的具体的值而是得到一个可迭代的对象。每一次获取这个可迭代对象的值就能推动函数的执行获取新的返回值。直到函数执行结束。
```python
import time
def genrator_func1():
a = 1
print('将a赋值')
yield a
b = 2
print('将b赋值')
yield b
g1 = genrator_func1()
print(g1,next(g1))
print(next(g1))
```
生成器不会一下子在内存中生成太多数据
比如我想卖包子让包子工厂开始加工10000个包子但是如果一下子全部生产好没地方放而且容易坏。
那么可以让包子工厂在我需要的时候再生产
```python
def produce():
'''生产包子'''
for i in range(10000):
yield '生产了第%s个包子'%i
produce_g = produce()
print(produce_g.__next__())
print(produce_g.__next__())
print(produce_g.__next__())
# 需要一批包子
num = 0
for i in produce_g:
print(i)
num += 1
if num == 5:
break
```
### send
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候给上一yield的位置传递一个数据
使用send的注意事项
* 第一次使用生成器的时候 是用next获取下一个值
* 最后一个yield不能接受外部的值
```python
def generator():
print(123)
content = yield 1
print('=========',content)
print(456)
yield 2
g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')
print('***',ret)
```
## 列表推导式和生成器表达式
```python
l = [i for i in range(10)]
print(l)
l1 = ['项目%s'%i for i in range(10)]
print(l1)
```
1. 把列表解析的[]换成()得到的就是生成器表达式
2. 列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3. Python不但使用迭代器协议让for循环变得更加通用。大部分内置函数也是使用迭代器协议访问对象的。例如 sum函数是Python的内置函数该函数使用迭代器协议访问对象而生成器实现了迭代器协议所以我们可以直接这样计算一系列值的和
```python
ret = sum(x for x in range(101))
print(ret)
```

View File

@@ -0,0 +1,73 @@
# 推导式
## 推导式详细格式
```plain
variable = [out_exp_res for out_exp in input_list if out_exp == 2]
out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
for out_exp in input_list  迭代input_list将out_exp传入out_exp_res表达式中。
if out_exp == 2  根据条件过滤哪些值可以。
```
## 列表推导式
30以内所有能被3整除的数
```python
multiples = [i for i in range(30) if i % 3 is 0]
print(multiples)
```
30以内所有能被3整除的数的平方
```python
def squared(x):
return x*x
multiples = [squared(i) for i in range(30) if i % 3 is 0]
print(multiples)
```
找到嵌套列表中名字含有两个及以上a的所有名字
```python
fruits = [['peach','Lemon','Pear','avocado','cantaloupe','Banana','Grape'],
['raisins','plum','apricot','nectarine','orange','papaya']]
print([name for lst in fruits for name in lst if name.count('a') >= 2])
```
## 字典推导式
将一个字典的key和value对调
```python
dic1 = {'a':1,'b':2}
dic2 = {dic1[k]: k for k in dic1}
print(dic2)
```
合并大小写对应的value值将k统一成小写
```python
dic1 = {'a':1,'b':2,'A':4,'Y':9}
dic2 = {k.lower():dic1.get(k.lower(),0) + dic1.get(k.upper(),0) for k in dic1.keys()}
print(dic2)
```
## 集合推导式
计算列表中每个值的平方,自带去重功能
```python
l = [1,2,3,4,1,-1,-2,3]
squared = {x**2 for x in l}
print(squared)
```
## 练习题
1. 过滤掉长度小于3的字符串列表并将剩下的转换成大写字母
2. 求(x,y)其中x是0-5之间的偶数y是0-5之间的奇数组成的元祖列表
3. 将1000以内的素数放入一个列表中

View File

@@ -0,0 +1,535 @@
# 内置函数与匿名函数
## 内置函数
截止到python版本3.6.2现在python一共为我们提供了**68个内置函数。**
| 内置函数 | | | | |
| :------------ | :---------- | :----------- | :--------- | :------------- |
| abs() | dict() | help() | min() | setattr() |
| all() | dir() | hex() | next() | slice() |
| any() | divmod() | id() | object() | sorted() |
| ascii() | enumerate() | input() | oct() | staticmethod() |
| bin() | eval() | int() | open() | str() |
| bool() | exec() | isinstance() | ord() | sum() |
| bytearray() | filter() | issubclass() | pow() | super() |
| bytes() | float() | iter() | print() | tuple() |
| callable() | format() | len() | property() | type() |
| chr() | frozenset() | list() | range() | vars() |
| classmethod() | getattr() | locals() | repr() | zip() |
| compile() | globals() | map() | reversed() | __import__() |
| complex() | hasattr() | max() | round() | |
| delattr() | hash() | memoryview() | set() | |
### 作用域相关
* locals :函数会以字典的类型返回当前位置的全部局部变量。
* globals函数以字典的类型返回全部全局变量。
```python
a = 1
b = 2
print(locals())
print(globals())
# 这两个一样,因为是在全局执行的
def func(argv):
c = 2
print(locals())
print(globals())
func(3)
```
### 其他相关
#### 字符串类型代码的执行 evalexeccomplie
* eval执行字符串类型的代码并返回最终结果。
```python
ret = eval('2 + 2')
print(ret)
n = 20
ret = eval('n + 23')
print(ret)
eval('print("Hello world")')
```
* exec:执行字符串类型的代码。
```python
s = '''
for i in range(5):
print(i)
'''
exec(s)
```
compile:将字符串类型的代码编译。代码对象能够通过exec语句来执行或者eval()进行求值。
1. 参数source字符串。即需要动态执行的代码段。
2. 参数 filename代码文件名称如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时filename参数传入空字符即可。
3. 参数model指定编译代码的种类可以指定为 exec,eval,single。当source中包含流程语句时model应指定为exec当source中只包含一个简单的求值表达式model应指定为eval当source中包含了交互式命令语句model应指定为'single'。
```python
# 流程语句使用exec
code1 = 'for i in range(5): print(i)'
compile1 = compile(code1,'','exec')
exec(compile1)
# 简单求值表达式用eval
code2 = '1 + 2 + 3'
compile2 = compile(code2,'','eval')
eval(compile2)
# 交互语句用single
code3 = 'name = input("please input you name: ")'
compile3 = compile(code3,'','single')
exec(compile3)
print(name)
```
有返回值的字符串形式的代码用eval没有返回值的字符串形式的代码用exec一般不用compile。
#### 输入输出相关 inputprint
* input:函数接受一个标准输入数据,返回为 string 类型。
* print:打印输出。
```python
''' 源码分析
def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
"""
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件
sep: 打印多个值之间的分隔符,默认为空格
end: 每一次打印的结尾,默认为换行符
flush: 立即把内容输出到流文件,不作缓存
"""
'''
print(11,22,33,sep='*')
print(11,22,33,end='')
print(44,55)
with open('log','w',encoding='utf-8') as f:
print('写入文件',file=f,flush=True)
```
#### 内存相关 hash id
* hash获取一个对象可哈希对象intstrBooltuple的哈希值。
```python
print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('aaron'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
```
* id:用于获取对象的内存地址。
```python
print(id('abc'))
print(id('123'))
```
#### 文件操作相关
* open函数用于打开一个文件创建一个 file 对象,相关的方法才可以调用它进行读写。
#### 模块相关`__import__`
* `__import__`:函数用于动态加载类和函数 。
#### 帮助
* help函数用于查看函数或模块用途的详细说明。
```python
print(help(print))
```
#### 调用相关
* callable函数用于检查一个对象是否是可调用的。如果返回Trueobject仍然可能调用失败但如果返回- False调用对象ojbect绝对不会成功。
```python
print(callable(0))
print(callable('hello'))
def demo1(a, b):
return a + b
print(callable(demo1))
class Demo2:
def test1(self):
return 0
print(callable(Demo2))
a = Demo2()
print(callable(a))
# 没有实现 __call__, 返回 False
```
#### 查看内置属性
* dir函数不带参数时返回当前范围内的变量、方法和定义的类型列表带参数时返回参数的属性、方法列表。如果参数包含方法`__dir__()`,该方法将被调用。如果参数不包含`__dir__()`,该方法将最大限度地收集参数信息。
```python
print(dir()) # 获得当前模块的属性列表
print(dir([ ])) # 查看列表的方法
```
### 迭代器生成器相关
* range函数可创建一个整数对象一般用在 for 循环中。
* next内部实际使用了`__next__`方法,返回迭代器的下一个项目。
```python
# 首先获得Iterator对象:
it = iter([1,2,3,4,5,6])
# 循环
while True:
try:
# 获得下一个值
x = next(it)
print(x)
except StopIteration: # 遇到StopIteration就退出循环
break
```
* iter函数用来生成迭代器讲一个可迭代对象生成迭代器
```python
from collections import Iterable
from collections import Iterator
l = [1,2,3,4] # 可迭代对象,但不是迭代器
print(isinstance(l,Iterable))
print(isinstance(l,Iterator))
l1 = iter(l) # 从一个可迭代对象生成迭代器
print(isinstance(l1,Iterable))
print(isinstance(l1,Iterator))
```
### 基础数据类型相关
#### 数字相关14个
数据类型4个
* bool :用于将给定参数转换为布尔类型,如果没有参数,返回 False。
* int函数用于将一个字符串或数字转换为整型。
```python
print(int())
print(int('12'))
print(int(3.6))
print(int('0100',base=2)) # 将2进制的 0100 转化成十进制。结果为 4
```
* float函数用于将整数和字符串转换成浮点数。
* complex函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。
```python
print(complex(1,2))
print(complex(1))
print(complex("1"))
print(complex("1+2j"))
```
进制转换3个
* bin将十进制转换成二进制并返回。
* oct将十进制转化成八进制字符串并返回。
* hex将十进制转化成十六进制字符串并返回。
```python
print(bin(10),type(bin(10)))
print(oct(10),type(oct(10)))
print(hex(10),type(hex(10)))
```
数学运算7
* abs函数返回数字的绝对值。
* divmod计算除数与被除数的结果返回一个包含商和余数的元组(a // b, a % b)。
* round保留浮点数的小数位数默认保留整数。 -pow函数是计算x的y次方如果z在存在则再对结果进行取模其结果等效于pow(x,y) %z
```python
print(abs(-5)) # 5
print(divmod(7,2)) # (3, 1)
print(round(7/3,2)) # 2.33
print(round(7/3)) # 2
print(round(3.32567,3)) # 3.326
print(pow(2,3)) # 8
print(pow(2,3,3)) # 2
```
* sum对可迭代对象进行求和计算可设置初始值
* min返回可迭代对象的最小值可加keykey为函数名通过函数的规则返回最小值
* max返回可迭代对象的最大值可加keykey为函数名通过函数的规则返回最大值
```python
print(sum([1,2,3]))
print(sum([1,2,3],100))
print(min([1,2,3]))
ret = min([1,2,3,-10],key=abs)
print(ret)
dic = {'a':3,'b':2,'c':1}
print(min(dic,key=lambda x:dic[x]))
# x为dic的keylambda的返回值即dic的值进行比较返回最小的值对应的键
print(max([1,2,3]))
ret = max([1,2,3,-10],key=abs)
print(ret)
dic = {'a':3,'b':2,'c':1}
print(max(dic,key=lambda x:dic[x]))
```
#### 数据结构相关24个
列表和元祖2个
* list将一个可迭代对象转化成列表如果是字典默认将key作为列表的元素
* tuple将一个可迭代对象转化成元祖如果是字典默认将key作为元祖的元素
```python
l = list((1,2,3))
print(l)
l = list({1,2,3})
print(l)
l = list({'k1':1,'k2':2})
print(l)
tu = tuple((1,2,3))
print(tu)
tu = tuple([1,2,3])
print(tu)
tu = tuple({'k1':1,'k2':2})
print(tu)
```
相关内置函数2个
* reversed将一个序列翻转并返回此翻转序列的迭代器。
* slice构造一个切片对象用于列表的切片。
```python
ite = reversed(['a',2,4,'f',12,6])
for i in ite:
print(i)
l = ['a','b','c','d','e','f','g']
sli = slice(3)
print(l[sli])
sli = slice(0,7,2)
print(l[sli])
```
字符串相关9
* str将数据转化成字符串。
* format:与具体数据相关,用于计算各种小数,精算等。
```python
# 字符串可以提供的参数,指定对齐方式,<是左对齐, >是右对齐,^是居中对齐
print(format('test','<20'))
print(format('test','>20'))
print(format('test','^20'))
# 整形数值可以提供的参数有 'b' 'c' 'd' 'o' 'x' 'X' 'n' None
print(format(192,'b')) # 转换为二进制
print(format(97,'c')) # 转换unicode成字符
print(format(11,'d')) # 转换成10进制
print(format(11,'o')) # 转换为8进制
print(format(11,'x')) # 转换为16进制小写字母表示
print(format(11,'X')) # 转换为16进制大写字母表示
print(format(11,'n')) # 和d一样
print(format(11)) # 和d一样
# 浮点数可以提供的参数有 'e' 'E' 'f' 'F' 'g' 'G' 'n' '%' None
print(format(314159265,'e')) # 科学计数法默认保留6位小数
print(format(314159265,'0.2e')) # 科学计数法保留2位小数
print(format(314159265,'0.2E')) # 科学计数法保留2位小数,大写E
print(format(3.14159265,'f')) # 小数点计数法默认保留6位小数
print(format(3.14159265,'0.10f')) # 小数点计数法保留10位小数
print(format(3.14e+10000,'F')) # 小数点计数法,无穷大转换成大小字母
# g的格式化比较特殊假设p为格式中指定的保留小数位数先尝试采用科学计数法格式化得到幂指数exp如果-4<=exp<p则采用小数计数法并保留p-1-exp位小数否则按小数计数法计数并按p-1保留小数位数
print(format(0.00003141566,'.1g'))
# p=1,exp=-5 ==》 -4<=exp<p不成立按科学计数法计数保留0位小数点
print(format(0.00003141566,'.2g'))
# p=2,exp=-5 ==》 -4<=exp<p不成立按科学计数法计数保留1位小数点
print(format(3.1415926777,'.1g'))
# p=1,exp=0 ==》 -4<=exp<p成立按小数计数法计数保留0位小数点
print(format(3.1415926777,'.2g'))
# p=2,exp=0 ==》 -4<=exp<p成立按小数计数法计数保留1位小数点
print(format(3141.5926777,'.2g'))
# p=2,exp=3 ==》 -4<=exp<p不成立按科学计数法计数保留1位小数点
print(format(0.00003141566,'.1n')) # 和g相同
print(format(0.00003141566)) # 和g相同
```
* bytes用于不同编码之间的转化。
```python
s = '你好'
bs = s.encode('utf-8')
print(bs)
s1 = bs.decode('utf-8')
print(s1)
bs = bytes(s,encoding='utf-8')
print(bs)
b = '你好'.encode('gbk')
b1 = b.decode('gbk')
print(b1.encode('utf-8'))
```
* bytearry返回一个新字节数组。这个数组里的元素是可变的并且每个元素的值范围: 0 <= x < 256
```python
ret = bytearray('aaron',encoding='utf-8')
print(id(ret))
print(ret)
print(ret[0])
ret[0] = 65
print(ret)
print(id(ret))
```
* memoryview: 内存查看对象是指对支持缓冲区协议的数据进行包装在不需要复制对象基础上允许Python代码访问
```python
ret = memoryview(bytes('你好',encoding='utf-8'))
print(len(ret))
print(ret)
print(bytes(ret[:3]).decode('utf-8'))
print(bytes(ret[3:]).decode('utf-8'))
```
* ord:输入字符找该字符编码的位置
* chr:输入位置数字找出其对应的字符
* ascii:是ascii码中的返回该值不是就返回/u
```python
# ord 输入字符找该字符编码的位置
print(ord('a'))
print(ord('中'))
# chr 输入位置数字找出其对应的字符
print(chr(97))
print(chr(20013))
# 是ascii码中的返回该值不是就返回/u...
print(ascii('a'))
print(ascii('中'))
```
* repr:返回一个对象的string形式
```python
name = 'aaron'
print('Hello %r'%name)
str1 = '{"name":"aaron"}'
print(repr(str1))
print(str1)
```
数据集合3个
* dict创建一个字典
* set创建一个集合
* frozenset返回一个冻结的集合冻结后集合不能再添加或删除任何元素
相关内置函数8个
* len:返回一个对象中元素的个数
* sorted对所有可迭代的对象进行排序操作
```python
l = [('a',1),('c',3),('d',4),('b',2)]
print(sorted(l,key=lambda x:x[1]))
print(sorted(l,key=lambda x:x[1],reverse=True)) # 降序
```
* enumerate: 用于将一个可遍历的数据对象(如列表元组或字符串)组合为一个索引序列同时列出数据和数据下标一般用在 for 循环当中
```python
print(enumerate([1,2,3]))
for i in enumerate([1,2,3]):
print(i)
for i in enumerate([1,2,3],100):
print(i)
```
* all可迭代对象中全都是True才是True
* any可迭代对象中有一个True 就是True
```python
print(all([1,2,True,0]))
print(any([1,'',0]))
```
* zip函数用于将可迭代的对象作为参数将对象中对应的元素打包成一个个元组然后返回由这些元组组成的列表如果各个迭代器的元素个数不一致则返回列表长度与最短的对象相同
```python
l1 = [1,2,3,]
l2 = ['a','b','c',5]
l3 = ('*','**',(1,2,3))
for i in zip(l1,l2,l3):
print(i)
```
filter用于过滤序列过滤掉不符合条件的元素返回由符合条件元素组成的新列表
```python
def func(x): return x%2 == 0
ret = filter(func,[1,2,3,4,5,6,7,8,9,10])
print(ret)
for i in ret:
print(i)
```
* map:会根据提供的函数对指定序列做映射Python 3.x 返回迭代器
```python
def square(x):
return x**2
ret1 = map(square,[1,2,3,4,5,6,7,8])
ret2 = map(lambda x:x ** 2,[1,2,3,4,5,6,7,8])
ret3 = map(lambda x,y : x+y,[1,2,3,4,5,6,7,8],[8,7,6,5,4,3,2,1])
for i in ret1:
print(i,end=' ')
print('')
for i in ret2:
print(i,end=' ')
print('')
for i in ret3:
print(i,end=' ')
```
## 匿名函数
匿名函数为了解决那些功能很简单的需求而设计的一句话函数
```python
# 这段代码
def calc(n):
return n ** n
print(calc(10))
# 换成匿名函数
calc = lambda n: n ** n
print(calc(10))
```
>匿名函数格式的说明
**函数名 = lambda 参数 :返回值**
1. 参数可以有多个,用逗号隔开
2. 匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值
3. 返回值和正常的函数一样可以是任意数据类型
```python
l=[3,2,100,999,213,1111,31121,333]
print(max(l))
dic={'k1':10,'k2':100,'k3':30}
print(max(dic))
print(dic[max(dic,key=lambda k:dic[k])])
res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:
print(i)
res = filter(lambda x:x>10,[5,8,11,9,15])
for i in res:
print(i)
```

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,367 @@
# 模块和包
## 什么是模块
1. 使用python编写的代码.py文件
2. 已被编译为共享库或DLL的C或C++扩展
3. 包好一组模块的包
4. 使用C编写并链接到python解释器的内置模块
## 为何要使用模块
实现代码和功能的复用
### import 自定义模块my_module.py
文件名my_module.py,模块名my_module
```python
# my_module.py
print('from the my_module.py')
money = 100
def read1():
print('my_module->read1->money',money)
def read2():
print('my_module->read2 calling read1')
read1()
def change():
global money
money=0
```
模块可以包含可执行的语句和函数的定义这些语句的目的是初始化模块它们只在模块名第一次遇到导入import语句时才执行import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入。
python的优化手段是第一次导入后就将模块名加载到内存了后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用不会重新执行模块内的语句
```python
import my_module
import my_module
import my_module
import my_module
import sys
print(sys.modules)
# sys.modules是一个字典内部包含模块名与模块对象的映射该字典决定了导入模块时是否需要重新导入。
```
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
```python
import my_module
money=10
print(my_module.money)
```
```python
import my_module
def read1():
print('=========')
my_module.read1()
```
```python
import my_module
money = 1
my_module.change()
print(money)
print(my_module.money)
```
总结首次导入模块my_module时会做三件事
1. 为源文件(my_module模块)创建新的名称空间在my_module中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2. 在新创 建的命名空间中执行模块中包含的代码
3. 创建名字my_module来引用该命名空间
#### 为模块名起别名相当于m1=1;m2=m1
```python
import my_module as mm
print(mm.money)
```
> 示范用法:
有两中sql模块mysql和oracle根据用户的输入选择不同的sql功能
```python
# mysql.py
def sqlparse():
print('from mysql sqlparse')
# oracle
def sqlparse():
print('from oracle sqlparse')
# test.py
db_type=input('>>: ')
if db_type == 'mysql':
import mysql as db
elif db_type == 'oracle':
import oracle as db
db.sqlparse()
```
#### 在一行导入多个模块
```python
import sys, os, re
```
### from ... import ...
对比import my_module会将源文件的名称空间'my_module'带到当前名称空间中使用时必须是my_module.名字的方式
而from 语句相当于import也会创建新的名称空间但是将my_module中的名字直接导入到当前的名称空间中在当前名称空间中直接使用名字就可以了
```python
from my_module import read1,read2
money = 1000
read1()
# 导入的函数read1执行时仍然回到my_module.py中寻找全局变量money
```
```python
from my_module import read1,read2
money = 1000
def read1():
print('*'*10)
read2()
# 导入的函数read2执行时需要调用read1(),仍然回到my_module.py中找read1()
```
```python
from my_module import read1,read2
money = 1000
def read1():
print('*'*10)
read1()
# 导入的函数read1被当前位置定义的read1覆盖掉了
```
```python
from my_module import read1 as read
read()
# 也支持as
```
from my_module import * 把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置
大部分情况下我们的python程序不应该使用这种导入方式因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
在my_module.py中新增一行
```python
.....
__all__ = ['money','read1']
# 这样在另外一个文件中用from my_module import *就这能导入列表中规定的两个名字
# test.py
from my_module import *
print(money)
read1()
read2()
```
<font color=red>注意如果my_module.py中的名字前加_,即_money则from my_module import *,则_money不能被导入</font>
- 编写好的一个python文件可以有两种用途
1. 脚本,一个文件就是整个程序,用来被执行
2. 模块,文件中存放着一堆功能,用来被导入使用
- python为我们内置了全局变量`__name__`
1. 当文件被当做脚本执行时:`__name__ 等于'__main__'`
2. 当文件被当做模块导入时:`__name__等于模块名`
- 作用:用来控制.py文件在不同的应用场景下执行不同的逻辑或者是在模块文件中测试代码
1. `if __name__ == '__main__':`
```python
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=',')
a, b = b, a+b
print()
if __name__ == "__main__":
print(__name__)
num = input('num :')
fib(int(num))
```
## 模块的搜索路径
模块的查找顺序是:内存中已经加载的模块->自建模块->sys.path路径中包含的模块
1. 在第一次导入某个模块时比如my_module会先检查该模块是否已经被加载到内存中当前执行文件的名称空间对应的内存如果有则直接引用
pspython解释器在启动时会自动加载一些模块到内存中可以使用sys.modules查看
2. 如果没有,解释器则会查找同名的内建模块
3. 如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。
<font color=red>注意:自定义的模块名不应该与系统内置模块重名</font>
## 编译python文件
为了提高加载模块的速度python解释器会在`__pycache__`目录中下缓存每个模块编译后的版本格式为module.version.pyc。通常会包含python的版本号。例如在CPython3.3版本下my_module.py模块会被缓存成`__pycache__/my_module.cpython-33.pyc`。这种命名规范保证了编译后的结果多版本共存。
## 包
包就是一个包含有`__init__.py`文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来
需要强调的是:
1. 在python3中即使包下没有`__init__.py`文件import 包仍然不会报错而在python2中包下一定要有该文件否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
### 为何要使用包
**包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起**来
随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性
### 注意事项
1. 关于包相关的导入语句也分为`import``from ... import ...`两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如`item.subitem.subsubitem`,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
2. import导入文件时产生名称空间中的名字来源于文件import 包,产生的名称空间的名字同样来源于文件,即包下的`__init__.py`,导入包本质就是在导入该文件
3. 包A和包B下有同名模块也不会冲突如A.a与B.a来自俩个命名空间
### 包的使用
示例文件
```python
glance/ #Top-level package
├── __init__.py #Initialize the glance package
├── api #Subpackage for api
├── __init__.py
├── policy.py
└── versions.py
├── cmd #Subpackage for cmd
├── __init__.py
└── manage.py
└── db #Subpackage for db
├── __init__.py
└── models.py
```
文件内容
```python
#文件内容
#policy.py
def get():
print('from policy.py')
##versions.py
def create_resource(conf):
print('from version.py: ',conf)
#manage.py
def main():
print('from manage.py')
#models.py
def register_models(engine):
print('from models.py: ',engine)
```
#### 使用import导入包
```python
import glance.db.models
# 在导入glance的时候会执行glance下的__init__.py中的代码
glance.db.models.register_models('mysql')
```
单独导入包名称时不会导入包中所有包含的所有子模块
```python
import glance
glance.cmd.manage.main()
```
解决方法
```python
# glance/__init__.py
from . import cmd
# glance/cmd/__init__.py
from . import manage
```
#### 使用from (具体的路径) import (具体的模块)
需要注意的是from后import导入的模块必须是明确的一个不能带点否则会有语法错误`from a import b.c`是错误语法
```python
from glance.db import models
from glance.db.models import register_models
models.register_models('mysql')
register_models('mysql')
```
`from glance.api import *`
想从包api中导入所有实际上该语句只会导入包api下`__init__.py`文件中定义的名字,我们可以在这个文件中定义`__all__`
```python
x = 10
def func():
print('from api.__init.py')
__all__=['x','func','policy']
```
```python
from glance.api import *
func()
print(x)
policy.get()
```
## 绝对导入和相对导入
- 绝对导入以glance作为起始
- 相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
1. 优点: 执行文件与被导入的模块中都可以使用
2. 缺点: 所有导入都是以sys.path为起始点,导入麻烦
相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
1. 符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
2. 优点: 导入更加简单
3. 缺点: 只能在导入包中的模块时才能使用
注意:
- 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
- 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@@ -0,0 +1,331 @@
# 异常处理
## 异常和错误
### 程序中难免出现错误,而错误分成两种
1. 语法错误这种错误根本过不了python解释器的语法检测必须在程序执行前就改正
```python
#语法错误示范一
if
#语法错误示范二
def test:
pass
#语法错误示范三
print(haha
```
### 逻辑错误
```python
#用户输入不完整(比如输入为空)或者输入非法(输入不是数字)
num=input(">>: ")
res1 = int(num)
#无法完成计算
res1=1/0
res2=1+'str'
```
### 异常
异常就是程序运行时发生错误的信号
异常之后的代码就不执行
![img](12.异常处理/1480155108.png)
### 异常种类
在python中不同的异常可以用不同的类型python中统一了类与类型类型即类去标识不同的类对象标识不同的异常一个异常标识一种错误
```python
# 触发IndexError
l=['eagle','aa']
l[3]
# 触发KeyError
dic={'name':'eagle'}
dic['age']
#触发ValueError
s='hello'
int(s)
```
常见异常
| AttributeError | 试图访问一个对象没有的属性比如foo.x但是foo没有属性x |
| :---------------- | :----------------------------------------------------------- |
| IOError | 输入/输出异常;基本上是无法打开文件 |
| ImportError | 无法引入模块或包;基本上是路径问题或名称错误 |
| IndentationError | 语法错误(的子类) ;代码没有正确对齐 |
| IndexError | 下标索引超出序列边界比如当x只有三个元素却试图访问x[5] |
| KeyError | 试图访问字典里不存在的键 |
| KeyboardInterrupt | Ctrl+C被按下 |
| NameError | 使用一个还未被赋予对象的变量 |
| SyntaxError | Python代码非法代码不能编译(个人认为这是语法错误,写错了) |
| TypeError | 传入对象类型与要求的不符合 |
| UnboundLocalError | 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 |
| ValueError | 传入一个调用者不期望的值,即使值的类型是正确的 |
其他错误
```python
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
```
## 异常处理
- python解释器检测到错误触发异常也允许程序员自己触发异常
- 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)
- 如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理
**首先须知,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正**
```python
num1=input('>>: ') #输入一个字符串试试
if num1.isdigit():
int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴
elif num1.isspace():
print('输入的是空格,就执行我这里的逻辑')
elif len(num1) == 0:
print('输入的是空,就执行我这里的逻辑')
else:
print('其他情情况,执行我这里的逻辑')
'''
问题一:
使用if的方式我们只为第一段代码加上了异常处理但这些if跟你的代码逻辑并无关系这样你的代码会因为可读性差而不容易被看懂
问题二:
这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。
'''
```
总结:
1. if判断式的异常处理只能针对某一段代码对于不同的代码段的相同类型的错误你需要写重复的if来进行处理。
2. 在你的程序中频繁的写与程序本身无关与异常处理有关的if会使得你的代码可读性极其的差
3. if是可以解决异常的只是存在1,2的问题所以千万不要妄下定论if不能用来异常处理。
```python
def test():
print('test.runing')
choice_dic = {
'1':test
}
while True:
choice = (input('>>: ').strip())
if not choice or choice not in choice_dic:continue
choice_dic[choice]()
```
**python为每一种异常定制了一个类型然后提供了一种特定的语法结构用来进行异常处理**
### 基本语法
```python
try:
被检测的代码块
except 异常类型
try中一旦检测到异常就执行这个位置的逻辑
```
将文件的每一行变成一个迭代器,然后读出来
```python
f = open('a.txt')
g = (line.strip() for line in f)
for line in g:
print(line)
else:
f.close()
```
但是如果超出了迭代器的范围就会出现`StopIteration`错误
使用异常处理
```python
try:
f = open('a.txt')
g = (line.strip() for line in f)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
except StopIteration:
f.close()
print('读取出错')
```
### 异常类只能用来处理指定的异常情况
```python
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print e
```
### 多分支
主要是用来针对不同的错误情况进行错误处理
```python
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
```
### 万能异常:Exception
```python
s1 = 'hello'
try:
int(s1)
except Exception as e:
print(e)
```
多分支加万能异常
```python
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
except Exception as e:
print(e)
```
## 其他异常情况
```python
s1 = '10'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
except Exception as e:
print(e)
else:
print('try内代码块没有异常则执行我')
finally:
print('无论异常与否,都会执行该模块,通常是进行清理工作')
```
### 主动触发异常
```python
try:
raise TypeError('类型错误')
except Exception as e:
print(e)
```
### 自定义异常
```python
class EvaException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise EvaException('类型错误')
except EvaException as e:
print(e)
```
### 断言
表达式位True时程序继续运行表达式为False时程序终止运行并报AssertionError错误
```python
assert 1 == 1
assert 1 == 2
```
### try..except的方式比较if的方式的好处
1. 把错误处理和真正的工作分开来
2. 代码更易组织,更清晰,复杂的工作任务更容易实现
3. 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

File diff suppressed because one or more lines are too long