1158 lines
34 KiB
Markdown
1158 lines
34 KiB
Markdown
- [Python](#python)
|
||
- [变量](#变量)
|
||
- [字符串](#字符串)
|
||
- [字符串首字母大写](#字符串首字母大写)
|
||
- [字符串全部字符大写](#字符串全部字符大写)
|
||
- [字符串全部字符小写](#字符串全部字符小写)
|
||
- [字符串删除空白符](#字符串删除空白符)
|
||
- [访问字符串中字符](#访问字符串中字符)
|
||
- [字符串切片](#字符串切片)
|
||
- [字符串迭代](#字符串迭代)
|
||
- [数字](#数字)
|
||
- [/](#)
|
||
- [//](#-1)
|
||
- [数字类型向字符串类型转换](#数字类型向字符串类型转换)
|
||
- [列表](#列表)
|
||
- [访问列表中元素](#访问列表中元素)
|
||
- [列表元素操作](#列表元素操作)
|
||
- [修改](#修改)
|
||
- [插入到末尾](#插入到末尾)
|
||
- [在某位置之前插入](#在某位置之前插入)
|
||
- [删除列表中的元素](#删除列表中的元素)
|
||
- [列表与栈api](#列表与栈api)
|
||
- [remove](#remove)
|
||
- [列表排序](#列表排序)
|
||
- [sort](#sort)
|
||
- [sorted](#sorted)
|
||
- [列表中顺序反转](#列表中顺序反转)
|
||
- [获取列表长度](#获取列表长度)
|
||
- [遍历列表](#遍历列表)
|
||
- [range](#range)
|
||
- [max, min, sum](#max-min-sum)
|
||
- [根据一个列表生成另一个列表](#根据一个列表生成另一个列表)
|
||
- [切片](#切片)
|
||
- [列表复制](#列表复制)
|
||
- [元组](#元组)
|
||
- [if](#if)
|
||
- [and/or](#andor)
|
||
- [列表中是否包含某值](#列表中是否包含某值)
|
||
- [列表中是否不包含某值](#列表中是否不包含某值)
|
||
- [多分支if/elif/else](#多分支ifelifelse)
|
||
- [字典](#字典)
|
||
- [向字典中添加键值对](#向字典中添加键值对)
|
||
- [删除字典中的键值对](#删除字典中的键值对)
|
||
- [字典遍历](#字典遍历)
|
||
- [按顺序遍历字典的key](#按顺序遍历字典的key)
|
||
- [while](#while)
|
||
- [函数](#函数)
|
||
- [参数默认值](#参数默认值)
|
||
- [接收多个参数](#接收多个参数)
|
||
- [文件操作](#文件操作)
|
||
- [文件读取](#文件读取)
|
||
- [写入文件](#写入文件)
|
||
- [文件末尾追加](#文件末尾追加)
|
||
- [module](#module)
|
||
- [运行module](#运行module)
|
||
- [module search path](#module-search-path)
|
||
- [dir](#dir)
|
||
- [package](#package)
|
||
- [from ... import \*](#from--import-)
|
||
- [异常处理](#异常处理)
|
||
- [抛异常](#抛异常)
|
||
- [捕获异常后重新抛出异常](#捕获异常后重新抛出异常)
|
||
- [主动抛出异常](#主动抛出异常)
|
||
- [数据存储](#数据存储)
|
||
- [json.dump](#jsondump)
|
||
- [json.load](#jsonload)
|
||
- [http api](#http-api)
|
||
- [多线程](#多线程)
|
||
- [linux命令交互](#linux命令交互)
|
||
- [正则](#正则)
|
||
- [match](#match)
|
||
- [search](#search)
|
||
- [pattern](#pattern)
|
||
- [findall](#findall)
|
||
- [finditer](#finditer)
|
||
- [面向对象](#面向对象)
|
||
- [命名空间](#命名空间)
|
||
- [module](#module-1)
|
||
- [module name](#module-name)
|
||
- [module statements](#module-statements)
|
||
- [when statements will be executed](#when-statements-will-be-executed)
|
||
- [from ... import ...](#from--import--1)
|
||
- [as](#as)
|
||
- [execute module as script](#execute-module-as-script)
|
||
|
||
|
||
# Python
|
||
## 变量
|
||
在python中,可以通过如下方式创建变量:
|
||
```python
|
||
message = "Hello Python Crash Course world!"
|
||
```
|
||
## 字符串
|
||
### 字符串首字母大写
|
||
```python
|
||
name = "ada lovelace"
|
||
print(name.title())
|
||
```
|
||
### 字符串全部字符大写
|
||
```python
|
||
name = "Ada Lovelace"
|
||
print(name.upper())
|
||
```
|
||
### 字符串全部字符小写
|
||
```python
|
||
name = "Ada Lovelace"
|
||
print(name.lower())
|
||
```
|
||
### 字符串删除空白符
|
||
```py
|
||
name = " Asahi Ogura `
|
||
# 删除左空白
|
||
name.lstrip()
|
||
# 删除右空白
|
||
name.rstrip()
|
||
# 删除左右空白
|
||
name.strip()
|
||
```
|
||
### 访问字符串中字符
|
||
ptyhon可以通过数组下标来访问字符串中的字符,如果字符串长度为n,那么索引范围为`[0, n-1]`,同时,在python中还可以使用负数的索引,索引范围为`[-n, -1]`。
|
||
|
||
在python字符串中,第一个字符可以通过索引下标`0`和`-n`来访问,最后一个字符可以通过`n-1`和`-1`来访问。
|
||
|
||
### 字符串切片
|
||
字符串切片可以通过`str[from:to:step]`来标识,其标识下标为`[from, to)`范围内的子字符串,步长为`step`。
|
||
|
||
```py
|
||
temp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||
```
|
||
|
||
其中,输出`[0,10)`范围内的字符串可以采用如下方式:
|
||
```py
|
||
print(temp[0:10]) # ABCDEFGHIJ
|
||
print(temp[0:10:1]) # ABCDEFGHIJ
|
||
```
|
||
|
||
当步长被设置为2时,输出内容如下:
|
||
```py
|
||
print(temp[0:10:2]) # ACEGI
|
||
```
|
||
|
||
正数索引和负数索引混用:
|
||
```py
|
||
# 输出不包含末尾2个字符的子字符串
|
||
print(temp[0:-2]) # ABCDEFGHIJKLMNOPQRSTUVWX
|
||
print(temp[0:24]) # ABCDEFGHIJKLMNOPQRSTUVWX
|
||
print(temp[:-2]) # ABCDEFGHIJKLMNOPQRSTUVWX
|
||
|
||
# 输出末尾两个字符的子字符串
|
||
print(temp[-2:])
|
||
```
|
||
逆序输出字字符串
|
||
```py
|
||
print(temp[::-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||
print(temp[-1:0:-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||
print(temp[25:0:-1]) # ZYXWVUTSRQPONMLKJIHGFEDCBA
|
||
```
|
||
### 字符串迭代
|
||
python中字符串可迭代,示例如下:
|
||
```py
|
||
temp = "ABCDE"
|
||
for ind, ch in enumerate(temp):
|
||
print("ind = "+str(ind)+", ch = "+ch, end="\n")
|
||
|
||
# ind = 0, ch = A
|
||
# ind = 1, ch = B
|
||
# ind = 2, ch = C
|
||
# ind = 3, ch = D
|
||
# ind = 4, ch = E
|
||
```
|
||
|
||
## 数字
|
||
### /
|
||
python中,整数执行`/`操作默认并不会进行整除,而是可能生成浮点数
|
||
```py
|
||
print(3/2) # 1.5
|
||
```
|
||
|
||
### //
|
||
python中,如果要执行整除,应该使用`//`运算符,该运算符为向下取整
|
||
```py
|
||
print(3//2) # 1
|
||
print(-3//2) # -2
|
||
```
|
||
> 和java不同,java在执行整数除时,会舍弃掉小数部分,例如`-3/2`,java中结果为-1,而python则是向下取整为-2
|
||
>
|
||
> 如果python中`/`操作想要和java保持一直,可以使用math中的`trunc`函数,`math.trunc(-3/2)`返回结果和java中一样,为`-1`
|
||
|
||
### 数字类型向字符串类型转换
|
||
可以通过str函数将数字类型转化为字符串类型
|
||
```py
|
||
temp = 1.2
|
||
print("temp = "+str(temp))
|
||
```
|
||
|
||
## 列表
|
||
python中通过`[e1, e2, ...]`的形式来标识列表
|
||
|
||
### 访问列表中元素
|
||
可以通过数组下标的方式来访问列表中的元素
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
print(temp[1]) # 2
|
||
print(temp[-2]) # 2
|
||
```
|
||
|
||
### 列表元素操作
|
||
#### 修改
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
temp[2] = 3.0
|
||
print(temp) # [1, '2', 3.0]
|
||
```
|
||
|
||
#### 插入到末尾
|
||
如果想要向数组末尾插入元素,可以调用append方法
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
temp.append("four")
|
||
print(temp) # [1, '2', 'san', 'four']
|
||
```
|
||
#### 在某位置之前插入
|
||
如果想要在特定位置之前插入元素,可以调用insert方法
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
temp.insert(1, "1.5")
|
||
print(temp) # [1, '1.5', '2', 'san']
|
||
temp.insert(4, "four")
|
||
print(temp) # [1, '1.5', '2', 'san', 'four']
|
||
```
|
||
#### 删除列表中的元素
|
||
如果想要删除列表中的元素,可以通过del关键字进行删除
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
del temp[1]
|
||
print(temp) # [1, 'san']
|
||
```
|
||
|
||
#### 列表与栈api
|
||
列表append操作是将元素追加到列表末尾,同时列表还支持pop操作,将列表末尾的元素作为栈顶元素弹出。
|
||
|
||
如果此时列表为空,那么调用pop方法将抛出异常
|
||
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
|
||
print(temp.pop()) # san
|
||
print(temp.pop()) # 2
|
||
print(temp.pop()) # 1
|
||
print(temp.pop()) # IndexError: pop from empty list
|
||
```
|
||
|
||
还可以为pop方法指定一个下标,此时可以弹出任何位置的元素
|
||
```py
|
||
temp = [1, "2", "san"]
|
||
|
||
|
||
print(temp.pop(1)) # 2
|
||
print(temp.pop(0)) # 1
|
||
print(temp.pop(0)) # san
|
||
```
|
||
#### remove
|
||
在列表中,可以调用remove来移除列表中值为xxx的元素。
|
||
|
||
remove默认只会移除第一个匹配的元素
|
||
```py
|
||
temp = [2, 1, 2, 1, 2]
|
||
|
||
temp.remove(2)
|
||
print(temp) # [1, 2, 1, 2]
|
||
```
|
||
|
||
### 列表排序
|
||
#### sort
|
||
可以通过sort方法针对列表中的元素进行排序,sort方法会该表列表中的元素顺序
|
||
```py
|
||
temp = [2, 1, 2, 1, 2]
|
||
|
||
temp.sort()
|
||
print(temp) # [1, 1, 2, 2, 2]
|
||
```
|
||
|
||
如果想要逆向排序,可以为sort方法指定`reverse=True`
|
||
```py
|
||
temp = [2, 1, 2, 1, 2]
|
||
|
||
temp.sort(reverse=True)
|
||
print(temp) # [2, 2, 2, 1, 1]
|
||
```
|
||
|
||
#### sorted
|
||
如果不想改变原列表中的元素顺序,而是生成一个排好序的新列表,可以调用sorted函数
|
||
```py
|
||
temp = [2, 1, 2, 1, 2]
|
||
|
||
print(sorted(temp)) # [1, 1, 2, 2, 2]
|
||
print(sorted(temp, reverse=True)) # [2, 2, 2, 1, 1]
|
||
print(temp) # [2, 1, 2, 1, 2]
|
||
```
|
||
|
||
### 列表中顺序反转
|
||
如果不想对列表中元素进行排序,只是想逆序列表中的数据,可以调用reverse方法
|
||
```py
|
||
temp = [2, 1, 2, 1, 3]
|
||
|
||
temp.reverse()
|
||
print(temp) # [3, 1, 2, 1, 2]
|
||
```
|
||
### 获取列表长度
|
||
可以通过len函数获取列表的长度
|
||
```py
|
||
temp = [1,2,3]
|
||
|
||
temp.pop()
|
||
print(len(temp)) # 2
|
||
temp.pop()
|
||
print(len(temp)) # 1
|
||
temp.pop()
|
||
print(len(temp)) # 0
|
||
```
|
||
|
||
### 遍历列表
|
||
在python中,可以通过`for ... in ...`的形式来遍历列表中的元素
|
||
```py
|
||
temp = [1, 2, 3]
|
||
|
||
for e in temp:
|
||
print(e)
|
||
|
||
# 1
|
||
# 2
|
||
# 3
|
||
```
|
||
|
||
### range
|
||
在python中,可以通过range函数生成一系列数字,`range(m,n)`会生成`[m,n)`范围内的数字,可用于`fori`形式的遍历
|
||
```py
|
||
arr = ["1", "3", "2"]
|
||
|
||
for ind in range(0, len(arr)):
|
||
print(arr[ind])
|
||
|
||
# 1
|
||
# 3
|
||
# 2
|
||
```
|
||
可以通过range函数来创建数字列表
|
||
```py
|
||
print(list(range(0, 5))) # [0, 1, 2, 3, 4]
|
||
```
|
||
|
||
range也可以指定步长
|
||
```py
|
||
print(list(range(0, 7, 2))) # [0, 2, 4, 6]
|
||
```
|
||
|
||
### max, min, sum
|
||
针对数字型的列表,支持max、min、sum等函数来求最大值、最小值、总和
|
||
```py
|
||
arr = list(range(1, 101))
|
||
|
||
print(max(arr)) # 100
|
||
print(min(arr)) # 1
|
||
print(sum(arr)) # 5050
|
||
```
|
||
### 根据一个列表生成另一个列表
|
||
python中,根据`[expr(e) for e in list_a]`的语法,可以快速根据一个列表得到应一个列表,目标列表中的每个元素都来源于来源列表的映射
|
||
```py
|
||
arr = ['amd', 'nvidia']
|
||
graphic_msgs = ['fuck '+brand for brand in arr]
|
||
print(graphic_msgs) # ['fuck amd', 'fuck nvidia']
|
||
```
|
||
|
||
### 切片
|
||
列表的切片和字符串切片类似
|
||
```py
|
||
arr = [1, 2, 3, 4, 5]
|
||
print(arr[::2]) # [1, 3, 5]
|
||
|
||
print([e**2 for e in arr[::2]]) # [1, 9, 25]
|
||
```
|
||
|
||
### 列表复制
|
||
在python中,如果要复制列表,可以创建整个列表的切片
|
||
```py
|
||
arr = [1, 2, 3]
|
||
# 复制列表
|
||
arr_copied = arr[:]
|
||
|
||
print(arr_copied) # [1, 2, 3]
|
||
|
||
# 对复制后的列表进行写操作,并不会影响复制前的列表
|
||
arr_copied.pop()
|
||
|
||
print(arr_copied) # [1, 2]
|
||
print(arr) # [1, 2, 3]
|
||
```
|
||
|
||
## 元组
|
||
运行时列表中的元素可以被修改,如果想要让元素不可变,可以使用元组。
|
||
|
||
元组通过`(e1, e2, e3, ...)`形式来表示,和列表一样,元组也可以通过索引来访问。
|
||
|
||
但是元组中的元素无法复制,在执行赋值语句时会抛出异常。
|
||
```py
|
||
pos = (50, 100)
|
||
|
||
pos[0] = 125 # TypeError:'tuple' object does not support item assignment
|
||
```
|
||
|
||
## if
|
||
类似其他编程语言,python也支持if/else语法
|
||
```py
|
||
cars = ['audi', 'bmw', 'subaru', 'toyota']
|
||
for car in cars:
|
||
if car == 'bmw':
|
||
print(car.upper())
|
||
else:
|
||
print(car.title())
|
||
```
|
||
|
||
### and/or
|
||
python可以通过`and`和`or`操作符来拼接多个条件。
|
||
```py
|
||
age = 179
|
||
is_alive = True
|
||
|
||
if age < 0 or age > 150 and is_alive:
|
||
print("age wired")
|
||
```
|
||
|
||
### 列表中是否包含某值
|
||
如果想要检查列表中是否包含特定值,可以采用`xxx in list_a`的语法。
|
||
```py
|
||
arr = [1, 3, 2]
|
||
|
||
print(1 in arr) # True
|
||
```
|
||
### 列表中是否不包含某值
|
||
如果想要检查列表中是否不包含特定值,可以采用`xxx not in list_a`的语法。
|
||
```py
|
||
arr = [1, 3, 2]
|
||
|
||
print(1 not in arr) # False
|
||
```
|
||
|
||
### 多分支if/elif/else
|
||
python可以通过if/elif/else的语法实现多分支判断
|
||
```py
|
||
age = 40
|
||
if age < 20:
|
||
print("teen")
|
||
elif age < 40:
|
||
print("man")
|
||
else:
|
||
print("elder man")
|
||
```
|
||
|
||
## 字典
|
||
在python中,通过字典实现了其他语言中的Map数据结构。
|
||
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
print(dic['name']) # Ogura Asahi
|
||
```
|
||
### 向字典中添加键值对
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
dic['major'] = "student"
|
||
print(dic) # {'name': 'Ogura Asahi', 'age': 17, 'major': 'student'}
|
||
```
|
||
|
||
### 删除字典中的键值对
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
del dic['age']
|
||
print(dic) # {'name': 'Ogura Asahi'}
|
||
```
|
||
|
||
### 字典遍历
|
||
字典遍历可以通过`for k, v in dic.items()`的形式完成
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
for key, val in dic.items():
|
||
print("key = "+key+" , value = "+str(val))
|
||
```
|
||
如果只想遍历字典的key集合,可以通过`for k in dic.keys()`的方式
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
for key in dic.keys():
|
||
print("key = "+key)
|
||
```
|
||
如果只想遍历字典的value集合,可以通过`for v in dic.values()`的形式
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
for value in dic.values():
|
||
print("value = "+str(value))
|
||
```
|
||
### 按顺序遍历字典的key
|
||
通常,字典的key遍历顺序是不一定的。如果想要按排序后的顺序遍历key,可以采用如下方式:
|
||
```py
|
||
dic = {"name": "Ogura Asahi", "age": 17}
|
||
|
||
for key in sorted(dic.keys()):
|
||
print("key = "+str(key))
|
||
```
|
||
## while
|
||
```py
|
||
i = 0
|
||
|
||
while i < 10:
|
||
print(i)
|
||
i += 1
|
||
```
|
||
## 函数
|
||
函数可通过如下方式来定义:
|
||
```py
|
||
def fuck(brand, boss):
|
||
print("fuck you " + boss + " and your " + brand)
|
||
|
||
|
||
fuck("Nvidia", "Jensen Huang")
|
||
```
|
||
|
||
在调用函数时,可以打乱传入实参顺序,只需要传参时指定参数名称即可:
|
||
```py
|
||
def fuck(brand, boss):
|
||
print("fuck you " + boss + " and your " + brand)
|
||
|
||
|
||
fuck(boss="Jensen Huang", brand="Nvidia")
|
||
```
|
||
### 参数默认值
|
||
声明函数时,可以为参数指定默认值,故而在调用函数时,可以对有默认值的参数进行省略
|
||
```py
|
||
def fuck(boss, brand="Nvidia"):
|
||
print("fuck you " + boss + " and your " + brand)
|
||
|
||
|
||
fuck("Jensen Huang")
|
||
fuck(brand="Apple", boss="Cook")
|
||
```
|
||
### 接收多个参数
|
||
通过`*paramTup`的形式,python会将函数接收到的参数都存储在一个元组中。
|
||
```py
|
||
def fuck(*name_list):
|
||
msg = "fuck "
|
||
is_head = True
|
||
for name in name_list:
|
||
if not is_head:
|
||
msg += ", "
|
||
is_head = False
|
||
msg += name
|
||
print(msg)
|
||
|
||
|
||
fuck("Nvidia", "Amd")
|
||
```
|
||
## 文件操作
|
||
### 文件读取
|
||
```py
|
||
with open('pi_digits.txt') as file_object:
|
||
contents = file_object.read()
|
||
print(contents)
|
||
```
|
||
### 写入文件
|
||
```py
|
||
filename = 'programming.txt'
|
||
with open(filename, 'w') as file_object:
|
||
file_object.write("I love programming.")
|
||
file_object.write("I love creating new games.")
|
||
```
|
||
|
||
### 文件末尾追加
|
||
```py
|
||
filename = 'programming.txt'
|
||
with open(filename, 'a') as file_object:
|
||
file_object.write("I also love finding meaning in large datasets.\n")
|
||
file_object.write("I love creating apps that can run in a browser.\n")
|
||
```
|
||
|
||
## module
|
||
在python中,支持将一些公用的实现放在一个文件中,在使用时可以在其他script中导入该文件并对公共实现进行调用。
|
||
|
||
此时,放置公共实现的文件称为module,module中的定义可以被其他module导入。
|
||
|
||
module是一个包含python定义和statement的文件,`file name`是`module name`加上`.py`。在module中,module name可以通过global变量`__main__`来进行访问。
|
||
|
||
|
||
module中可以包含executable statement和函数定义,statements则是为了初始化module。executable statement只会在module被初次import时执行。
|
||
|
||
每个module都会有其独有的private namespace,该namespace会用作module中所有函数的global namespace。故而,module的作者可以放心的在mdoule中使用global变量,module global变量有其自己的namespace,并不用担心module global变量和调用方的global变量发生冲突。
|
||
|
||
故而,可以通过`modname.itemname`来访问module中的global变量。
|
||
|
||
如果在`module A`中对`module B`执行了导入操作,那么被导入的`module B`中的names将会被全部添加到`module A`的global namespace中。
|
||
|
||
导入语法如下:
|
||
|
||
```python
|
||
# 直接导入fibo中的names
|
||
from fibo import fib, fib2
|
||
fib(500)
|
||
```
|
||
|
||
```python
|
||
# 从module中导入所有names,_开头的name不会被导入
|
||
from fibo import *
|
||
fib(500)
|
||
```
|
||
|
||
```python
|
||
# 如果import语句后跟随了as,那么as后跟随的名称将会和被导入module绑定
|
||
import fibo as fib
|
||
fib.fib(500)
|
||
```
|
||
|
||
```python
|
||
# 和上一个的效果相同,module通过`fibo`来引用
|
||
import fibo
|
||
```
|
||
|
||
```python
|
||
from fibo import fib as fibonacci
|
||
fibonacci(500)
|
||
```
|
||
### 运行module
|
||
当想要运行module时,可以采用如下方法:
|
||
```bash
|
||
python fibo.py <arguments>
|
||
```
|
||
当有一段代码,只有当module以main module的情况下被调用时才会被执行,可以采用如下方式
|
||
```python
|
||
if __name__ == '__main__':
|
||
# run some code
|
||
```
|
||
|
||
### module search path
|
||
当module被导入时,python interpreter首先会在`sys.builtin_module_names`中搜寻module name,built-in-module-names中包含如下module:
|
||
```ptyhon3
|
||
>>> import sys
|
||
>>> sys.builtin_module_names
|
||
('_abc', '_ast', '_bisect', '_blake2', '_codecs', '_collections', '_csv', '_datetime', '_elementtree', '_functools', '_heapq', '_imp', '_io', '_locale', '_md5', '_operator', '_pickle', '_posixsubprocess', '_random', '_sha1', '_sha256', '_sha3', '_sha512', '_signal', '_socket', '_sre', '_stat', '_statistics', '_string', '_struct', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'array', 'atexit', 'binascii', 'builtins', 'cmath', 'errno', 'faulthandler', 'fcntl', 'gc', 'grp', 'itertools', 'marshal', 'math', 'posix', 'pwd', 'pyexpat', 'select', 'spwd', 'sys', 'syslog', 'time', 'unicodedata', 'xxsubtype', 'zlib')
|
||
>>>
|
||
```
|
||
如果builtin_module_names中不包含被导入的module name,那么其会在`sys.path`中寻找`{module}.py`文件,`sys.path`通过如下路径来初始化:
|
||
- input script所处的目录路径
|
||
- `PYTHONPATH`全局变量,语法和`PATH`相同
|
||
- 安装包默认位置
|
||
|
||
### dir
|
||
通过内置的dir函数,可以输出module中的names
|
||
```bash
|
||
>>>import fibo, sys
|
||
>>>dir(fibo)
|
||
['__name__', 'fib', 'fib2']
|
||
>>>dir(sys)
|
||
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
|
||
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
|
||
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
|
||
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
|
||
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
|
||
'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
|
||
'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
|
||
'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
|
||
'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
|
||
'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
|
||
'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
|
||
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
|
||
'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
|
||
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
|
||
'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
|
||
'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
|
||
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
|
||
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
|
||
'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
|
||
'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
|
||
'warnoptions']
|
||
```
|
||
当dir函数传参为空时,输出当前namespace的names
|
||
```bash
|
||
>>>a = [1, 2, 3, 4, 5]
|
||
>>>import fibo
|
||
>>>fib = fibo.fib
|
||
>>>dir()
|
||
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
|
||
```
|
||
dir并不会输出内置的names,内置的names定义在`builtins`module中:
|
||
```bash
|
||
>>>import builtins
|
||
>>>dir(builtins)
|
||
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
|
||
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
|
||
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
|
||
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
|
||
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
|
||
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
|
||
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
|
||
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
|
||
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
|
||
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
|
||
'NotImplementedError', 'OSError', 'OverflowError',
|
||
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
|
||
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
|
||
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
|
||
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
|
||
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
|
||
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
|
||
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
|
||
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
|
||
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
|
||
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
|
||
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
|
||
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
|
||
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
|
||
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
|
||
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
|
||
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
|
||
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
|
||
'zip']
|
||
```
|
||
### package
|
||
假设python项目结构如下,package和子package中包含多个moduels:
|
||
```
|
||
sound/ Top-level package
|
||
__init__.py Initialize the sound package
|
||
formats/ Subpackage for file format conversions
|
||
__init__.py
|
||
wavread.py
|
||
wavwrite.py
|
||
aiffread.py
|
||
aiffwrite.py
|
||
auread.py
|
||
auwrite.py
|
||
...
|
||
effects/ Subpackage for sound effects
|
||
__init__.py
|
||
echo.py
|
||
surround.py
|
||
reverse.py
|
||
...
|
||
filters/ Subpackage for filters
|
||
__init__.py
|
||
equalizer.py
|
||
vocoder.py
|
||
karaoke.py
|
||
...
|
||
```
|
||
在导入包时,会在sys.path中搜索package的子目录。
|
||
|
||
如果需要python将目录视为package,需要在目录下加入`__init__.py`文件,该文件可以为空。
|
||
|
||
使用者可以导入package中独立的模块:
|
||
```python
|
||
import sound.effects.echo
|
||
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
|
||
```
|
||
|
||
```python
|
||
from sound.effects import echo
|
||
echo.echofilter(input, output, delay=0.7, atten=4)
|
||
```
|
||
#### from ... import *
|
||
对于`from {package} import *`,其会查看是否包下定义的`__init__.py`文件中定义了`__all__`变量,如果定义了,那么会导入`__all__`中的所有module。
|
||
|
||
```python
|
||
__all__ = ["echo", "surround", "reverse"]
|
||
```
|
||
|
||
## 异常处理
|
||
在python中,可以通过如下语法来进行异常处理
|
||
```py
|
||
try:
|
||
# code block
|
||
pass
|
||
except ErrorType1:
|
||
# error type 1 handling code block
|
||
pass
|
||
except ErrorType2:
|
||
# error type 2 handling code block
|
||
pass
|
||
except Exception as result:
|
||
# handle other exception types
|
||
pass
|
||
else:
|
||
# code block that no error occurs
|
||
pass
|
||
finally:
|
||
# code block executed whether exception occurs
|
||
pass
|
||
```
|
||
|
||
### 抛异常
|
||
#### 捕获异常后重新抛出异常
|
||
如果python在捕获异常后需要重新对异常进行抛出,可以使用`raise`关键字
|
||
```py
|
||
try:
|
||
m = 10/0
|
||
except Exception as e:
|
||
print(e)
|
||
raise
|
||
finally:
|
||
print("handle correctly")
|
||
```
|
||
#### 主动抛出异常
|
||
主动抛出异常时,也可使用`raise`关键字
|
||
```py
|
||
try:
|
||
raise Exception("fucking Nvidia raised their price!")
|
||
except Exception as e:
|
||
print(e)
|
||
finally:
|
||
print("my wallet is empty!")
|
||
```
|
||
|
||
## 数据存储
|
||
### json.dump
|
||
可以通过`json.dump`方法将内容以json的格式存储到文件中:
|
||
```py
|
||
import json
|
||
|
||
|
||
def save_as_json(data, fd):
|
||
json.dump(data, fd)
|
||
|
||
|
||
waifu = {
|
||
"name": "Touma Kazusa",
|
||
"job": "Student",
|
||
"gender": "female",
|
||
"age": 17
|
||
}
|
||
|
||
is_save_success = True
|
||
try:
|
||
with open("shiro.json", "w") as shiro_fd:
|
||
save_as_json(waifu, shiro_fd)
|
||
except Exception as e:
|
||
print(e)
|
||
is_save_success = False
|
||
exit(1)
|
||
finally:
|
||
if is_save_success:
|
||
print("save success!")
|
||
```
|
||
### json.load
|
||
可以通过`json.load`方法读取文件中的json格式内容:
|
||
```py
|
||
import json
|
||
|
||
|
||
def read_as_json(fd):
|
||
return json.load(fd)
|
||
|
||
|
||
is_read_success = True
|
||
try:
|
||
with open("shiro.json", "r") as shiro_fd:
|
||
r_obj = read_as_json(shiro_fd)
|
||
print(r_obj)
|
||
except Exception as e:
|
||
print(e)
|
||
is_read_success = False
|
||
exit(1)
|
||
finally:
|
||
if is_read_success:
|
||
print("read success!")
|
||
```
|
||
## http api
|
||
python安装requests包之后,可以访问http接口
|
||
```py
|
||
import math
|
||
import requests
|
||
import time
|
||
|
||
try:
|
||
body = requests.get("https://api.m.taobao.com/rest/api3.do", {
|
||
"api": "mtop.common.getTimestamp"
|
||
}).json()
|
||
ts = body['data']['t']
|
||
t = time.localtime(math.trunc(int(ts) / 1000))
|
||
time_str = time.strftime("%Y-%m-%d %H:%M:%S %z", t)
|
||
print(time_str)
|
||
except Exception as e:
|
||
print(e)
|
||
raise
|
||
```
|
||
|
||
## 多线程
|
||
python可以通过引入threading和concurrent.futures两个包来引入多线程:
|
||
```py
|
||
import math
|
||
import time
|
||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||
import threading
|
||
|
||
import requests
|
||
|
||
ts_arr = []
|
||
lock = threading.Lock()
|
||
|
||
|
||
def query_ts():
|
||
try:
|
||
body = requests.get("https://api.m.taobao.com/rest/api3.do", {
|
||
"api": "mtop.common.getTimestamp"
|
||
}).json()
|
||
except Exception as e:
|
||
print(e)
|
||
raise
|
||
|
||
|
||
def query_ts_once():
|
||
ts_beg = time.time_ns()
|
||
query_ts()
|
||
ts_end = time.time_ns()
|
||
ts_spend = math.trunc((ts_end - ts_beg) / 1000000)
|
||
with lock:
|
||
ts_arr.append(ts_spend)
|
||
|
||
|
||
def stress_test(test_cnt):
|
||
with ThreadPoolExecutor(max_workers=32) as executor:
|
||
i = 0
|
||
f_list = []
|
||
while i < test_cnt:
|
||
f_t = executor.submit(query_ts_once)
|
||
f_list.append(f_t)
|
||
i += 1
|
||
as_completed(f_list)
|
||
|
||
|
||
stress_test(100)
|
||
print(f"max ts : {max(ts_arr)} ms")
|
||
print(f"min ts : {min(ts_arr)} ms")
|
||
print(f"avg ts : {sum(ts_arr) / len(ts_arr)} ms")
|
||
print(ts_arr)
|
||
```
|
||
|
||
## linux命令交互
|
||
如果想要调用系统(linux)的命令,可以使用subprocess模块。
|
||
```py
|
||
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
|
||
```
|
||
调用示例如下:
|
||
```py
|
||
ret = subprocess.run(['ls', '-l'], capture_output=True, text=True)
|
||
print(ret.stdout)
|
||
```
|
||
输出如下:
|
||
```bash
|
||
total 4
|
||
-rwxrwxrwx 1 asahi asahi 110 May 4 03:18 main.py
|
||
-rwxrwxrwx 1 asahi asahi 73 May 4 01:10 shiro.json
|
||
drwxrwxrwx 1 asahi asahi 4096 Feb 7 21:39 venv
|
||
```
|
||
|
||
## 正则
|
||
python通过re模块提供了正则表达式的支持
|
||
### match
|
||
match方法定义如下所示
|
||
```py
|
||
re.match(pattern, string, flags=0)
|
||
```
|
||
match方法使用示例如下所示:
|
||
```py
|
||
import re
|
||
|
||
|
||
def main():
|
||
match_res = re.match("(?P<prefix>.*) father", "i am your father")
|
||
if match_res is None:
|
||
print("failed match")
|
||
return
|
||
print(match_res.group("prefix")) # i am your
|
||
print(match_res.group(0)) # i am your father
|
||
|
||
|
||
main()
|
||
```
|
||
|
||
### search
|
||
search方法定义如下所示
|
||
```py
|
||
re.search(pattern, string, flags=0)
|
||
```
|
||
search方法使用示例如下所示
|
||
|
||
### pattern
|
||
类似java,re提供了compile方法,返回正则编译后的pattern,并通过pattern执行操作
|
||
|
||
#### findall
|
||
`pattern.findall`方法会返回所有匹配的字符串
|
||
```py
|
||
import re
|
||
|
||
|
||
def main():
|
||
msg = '''although i use amd graphic card, i view it as a trash for its bad performance in ai.
|
||
nvidia is also trash because its crazy price, fuck amd and nvidia!'''
|
||
pattern = re.compile("(amd|nvidia)\\s+(graphic card)?")
|
||
search_res_list = pattern.findall(msg)
|
||
print(search_res_list)
|
||
|
||
|
||
main()
|
||
|
||
# [('amd', 'graphic card'), ('nvidia', ''), ('amd', '')]
|
||
```
|
||
#### finditer
|
||
`pattern.finditer`会返回所有匹配的match对象
|
||
```py
|
||
import re
|
||
|
||
|
||
def main():
|
||
msg = '''although i use amd graphic card, i view it as a trash for its bad performance in ai.
|
||
nvidia is also trash because its crazy price, fuck amd and nvidia!'''
|
||
pattern = re.compile("(amd|nvidia)\\s+(graphic card)?")
|
||
search_res_list = pattern.finditer(msg)
|
||
print([e.group(0) for e in search_res_list])
|
||
|
||
|
||
main()
|
||
|
||
# ['amd graphic card', 'nvidia ', 'amd ']
|
||
```
|
||
|
||
## 面向对象
|
||
### 命名空间
|
||
命名空间是name到对象的映射集合,在不同的命名空间中,相同name映射到的对象可能会不同。
|
||
|
||
namespace的示例有:
|
||
- 内置name集合:(包含内置异常名称和函数名,例如`abs()`函数)
|
||
- module中的global names
|
||
- 函数调用中的local names
|
||
|
||
> 在某种程度上来说,对象中的attributes也构成了一个命名空间
|
||
|
||
## module
|
||
python支持将文件内容拆分到多个文件中,将function definition放置到文件中后,在`其他文件`或`interactive instance`中可以针对fucntion definition进行导入。
|
||
|
||
放置function definition的文件被称之为`module`,通常用来定义公共方法。
|
||
|
||
### module name
|
||
module为包含python definition和statements的文件。file name由module name和`.py`后缀组成。在module中,module的名称可以通过全局变量名`__name__`进行访问。
|
||
|
||
如果在文件`fibo.py`中定义如下内容:
|
||
```py
|
||
# Fibonacci numbers module
|
||
|
||
def fib(n):
|
||
"""Write Fibonacci series up to n."""
|
||
a, b = 0, 1
|
||
while a < n:
|
||
print(a, end=' ')
|
||
a, b = b, a+b
|
||
print()
|
||
|
||
def fib2(n):
|
||
"""Return Fibonacci series up to n."""
|
||
result = []
|
||
a, b = 0, 1
|
||
while a < n:
|
||
result.append(a)
|
||
a, b = b, a+b
|
||
return result
|
||
```
|
||
那么`fibo`module中的内容可以通过如下方式进行导入
|
||
```py
|
||
import fibo
|
||
```
|
||
上述导入并不会将定义在`fibo`module中的function name直接添加到当前的命名空间,其只是将module name`fibo`添加到了命名空间,可以通过module name访问module中定义的内容:
|
||
```py
|
||
fibo.fib(1000)
|
||
|
||
fibo.fib2(100)
|
||
|
||
fibo.__name__
|
||
```
|
||
### module statements
|
||
在module中除了可以包含function definition外,还可以包含可执行statements。该可执行statements用于对module进行初始化。
|
||
|
||
#### when statements will be executed
|
||
module中的statements只会在`第一次该module被导入`时执行。(如果module文件其本身被执行,而非作为依赖被其他文件导入,那么module中的statements也同样会被执行)
|
||
|
||
每个module都拥有其自己的private namespace,并且对于定义在module中的所有方法而言,`private module`既是`global namespace`。故而,作为module的开发者而言,其可以自由的使用global variables,而不用担心其global variables名称和module使用者定义的global variables发生冲突。
|
||
|
||
如果想要访问在module中定义的global variables,可以使用`modname.itemname`的方式。
|
||
|
||
通常而言,对于module的import被放置在文件的最外层最开始的部分,`但这并非是必须的`。在文件最外层被导入的module,其module name会被添加到当前文件的module glboal namespace中。
|
||
|
||
#### from ... import ...
|
||
import还存在一个变体,可以从module中直接导入name,而不是导入module后通过module name访问module中内容:
|
||
```py
|
||
from fibo import fib, fib2
|
||
fib(500)
|
||
```
|
||
在上述示例中,`fibo`并没有被引入到当前文件的global namespace中。
|
||
|
||
除此之外,还可以导入module中所有的name
|
||
```py
|
||
from fibo import *
|
||
fib(500)
|
||
```
|
||
同样的,`fibo`也不会被导入到当前global namespace中。
|
||
|
||
上述`from fibo import *`语句会导入`fibo`module中定义的所有name,但是以下划线`_`开头的名称除外。
|
||
|
||
通常情况下,不要使用`from fibo import *`来进行导入,因为其引入的name是不确定的,可能会覆盖你所定义的部分内容。
|
||
|
||
#### as
|
||
在对其他module执行import操作时,可以通过as来进行重命名
|
||
|
||
```py
|
||
import fibo as fib
|
||
fib.fib(500)
|
||
```
|
||
上述示例中,`fib`的名称将会绑定到module `fibo`。
|
||
|
||
```py
|
||
from fibo import fib as fibonacci
|
||
fibonacci(500)
|
||
```
|
||
|
||
### execute module as script
|
||
当想要将module作为script执行时,可以使用如下命令:
|
||
```bash
|
||
python fibo.py <arguments>
|
||
```
|
||
|
||
上述`将module作为script执行的命令`,和`导入module时对module进行执行`的行为实际上是一致的,唯一区别如下:
|
||
- `module作为script执行`: `__name__`值为`__main__`
|
||
- `module被导入`: `__name__`值为`module name`
|
||
|
||
故而,在module中包含如下代码
|
||
```py
|
||
if __name__ == "__main__":
|
||
import sys
|
||
fib(int(sys.argv[1]))
|
||
```
|
||
可以使module既可作为module被导入,也可以作为可执行的脚本,其中该代码块只会在module作为main file时才会被执行。
|
||
|
||
并且,在module被导入时,`sys`并不会被导入。
|
||
|