first commit
913
01.基础语法/01.python基础.md
Normal file
@@ -0,0 +1,913 @@
|
||||
# Python基础
|
||||
|
||||
## 安装python
|
||||
|
||||
略
|
||||
|
||||
## 运行python代码
|
||||
|
||||
在硬盘创建文件 t1.py,并且使用 PyCharm 打开,输入以下代码
|
||||
|
||||
```python
|
||||
print('Hello World!')
|
||||
```
|
||||
|
||||
然后右键运行
|
||||
|
||||

|
||||
|
||||
运行结果
|
||||
|
||||
```
|
||||
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"
|
||||
```
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
```python
|
||||
a = "变量1"
|
||||
b = a
|
||||
```
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 常量
|
||||
|
||||
常量即指不变的量,如 pi 3.141592653..., 或在程序运行过程中不会改变的量。
|
||||
|
||||
## 程序交互
|
||||
|
||||
```python
|
||||
name = input("请输入姓名:")
|
||||
print(name)
|
||||
```
|
||||
|
||||
执行脚本就会发现,程序会等待你输入姓名后再往下继续走。
|
||||
|
||||
```python
|
||||
请输入姓名:Aaron
|
||||
Aaron
|
||||
```
|
||||
|
||||
## 基础数据类型
|
||||
|
||||
### 整数型(int)
|
||||
|
||||
在 32 位机器上,整数的位数为 32 位,取值范围为 -2**31~2**31-1,即 -2147483648~2147483647
|
||||
|
||||
在 64 位系统上,整数的位数为 64 位,取值范围为 -2**63~2**63-1,即 -9223372036854775808~9223372036854775807
|
||||
|
||||
注意:在 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 优先级高于 and,and 优先级高于 or,即优先级关系为()>not>and>or,同一优先级从左往右计算。
|
||||
|
||||
x or y , x 为真,值就是 x,x 为假,值是 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
|
||||
|
||||
布尔值就两种:True,False。就是反应条件的正确与否。
|
||||
|
||||
真 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值访问(映射类型) | 字典 |
|
||||
|
||||
## 其他(for,enumerate,range)
|
||||
|
||||
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)
|
||||
```
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 15 KiB |
321
01.基础语法/02.python文件操作.md
Normal 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 | 写读【可写,可读】 |
|
||||
|
||||
|
||||
|
||||
## 文件操作方法
|
||||
|
||||
|
||||
|
||||
### 常用操作方法
|
||||
|
||||
|
||||
|
||||
read(3):
|
||||
|
||||
|
||||
|
||||
1. 文件打开方式为文本模式时,代表读取3个字符
|
||||
2. 文件打开方式为b模式时,代表读取3个字节
|
||||
|
||||
|
||||
|
||||
其余的文件内光标移动都是以字节为单位的如:seek,tell,truncate
|
||||
|
||||
|
||||
|
||||
注意:
|
||||
|
||||
|
||||
|
||||
1. seek有三种移动方式0,1,2,其中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
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 文件的修改
|
||||
|
||||
|
||||
|
||||
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
|
||||
|
||||
|
||||
|
||||
方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)
|
||||
|
||||
|
||||
|
||||
```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)
|
||||
```
|
410
01.基础语法/03.python认识函数.md
Normal 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)
|
||||
```
|
||||
|
||||
对可变数据类型(list,dict,set)可以直接引用不用通过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'))
|
||||
```
|
175
01.基础语法/04.装饰器.md
Normal 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)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,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()
|
||||
```
|
||||
|
177
01.基础语法/05.迭代器与生成器.md
Normal 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又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
|
||||
|
||||
```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)
|
||||
```
|
||||
|
73
01.基础语法/06.推导式.md
Normal 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以内的素数放入一个列表中
|
||||
|
||||
|
||||
|
535
01.基础语法/07.内置函数与匿名函数.md
Normal 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)
|
||||
```
|
||||
|
||||
### 其他相关
|
||||
|
||||
#### 字符串类型代码的执行 eval,exec,complie
|
||||
|
||||
* 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。
|
||||
|
||||
#### 输入输出相关 input,print
|
||||
|
||||
* 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:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。
|
||||
|
||||
```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:函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回- 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:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。
|
||||
* max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)。
|
||||
|
||||
```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的key,lambda的返回值(即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)
|
||||
```
|
139
01.基础语法/08.递归函数.md
Normal file
367
01.基础语法/09.模块和包.md
Normal 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),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
|
||||
ps:python解释器在启动时会自动加载一些模块到内存中,可以使用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. 缺点: 只能在导入包中的模块时才能使用
|
||||
注意:
|
||||
|
||||
- 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
|
||||
- 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包
|
1377
01.基础语法/10.常用模块.md
Normal file
BIN
01.基础语法/10.常用模块/3856406007.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
01.基础语法/10.常用模块/5NnyAJyLO6F1x0aY.png!thumbnail
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
01.基础语法/10.常用模块/5sL2I6iz3J2Qn00r.png!thumbnail
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
01.基础语法/10.常用模块/838049513.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
01.基础语法/10.常用模块/987936105.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
01.基础语法/10.常用模块/VA9mmGsaAk8HNGKh.png!thumbnail
Normal file
After Width: | Height: | Size: 77 KiB |
331
01.基础语法/12.异常处理.md
Normal 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'
|
||||
```
|
||||
|
||||
### 异常
|
||||
|
||||
异常就是程序运行时发生错误的信号
|
||||
异常之后的代码就不执行
|
||||
|
||||

|
||||
|
||||
### 异常种类
|
||||
|
||||
在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. 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了
|
BIN
01.基础语法/12.异常处理/1480155108.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
01.基础语法/12.异常处理/YG9kCGCs3sF9bTJI.png!thumbnail
Normal file
After Width: | Height: | Size: 203 KiB |