Files
rikako-note/python/py.md

1158 lines
34 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- [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中导入该文件并对公共实现进行调用。
此时放置公共实现的文件称为modulemodule中的定义可以被其他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 namebuilt-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
类似javare提供了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`并不会被导入。