Python3.8速通
数据类型
官方文档:https://docs.python.org/zh-cn/3.8/library/stdtypes.html#
数字、二进制(略)
字符串
str对象,即字符串。单引号'xxx'
、双引号"xxx"
、三重引号"""xxx"""
表示。由Unicode码构成的不可变序列,实现了所有一般序列的操作(略)
format()函数
通过format对字符串进行占位操作。或者使用另一种写法f"xxx……"
,注意使用该写法时{}中应使用变量名,而非index
1 |
|
方式 | 内容 |
---|---|
:, | 每 3 个 0 就用逗号隔开,比如 1,000 |
:b | 该数字的二进制 |
:d | 整数型 |
:f | 小数模式 |
:% | 百分比模式 |
字符串修改
方式 | 意思 | 例子 |
---|---|---|
strip | 去除两端的空白符 | “ 我不想要前后的空白,但是 中间\n的可以有\n “.strip() |
replace | 替换字符,未找到不替换不报错 | “帮我替换掉你好”.replace(“你好”, “Hello”) |
lower | 全部做小写处理 | print(“How ABOUT lower CaSe?”.lower()) |
upper | 全部做大写处理 | print(“And upper CaSe?”.upper()) |
title | 仅开头的字母大写 | print(“do tiTle For me”.title()) |
split | 按要求分割 | `print(“你 |
join | 按要求合并 | `print(“ |
startswith | 判断是否为某字段开头 | print(“我在街头看到你”.startswith(“我在”)) |
endswith | 判断是否为某字段结尾 | print(“我在巷尾看到你”.endswith(“看到你”)) |
一般序列
三种基本序列操作:list、tuple、range。大部分序列均支持以下操作
x in s |
如果 s 中的某项等于 x 则结果为 True ,否则为 False |
(1) |
---|---|---|
x not in s |
如果 s 中的某项等于 x 则结果为 False ,否则为 True |
(1) |
s + t |
s 与 t 相拼接 | (6)(7) |
s * n 或 n * s |
相当于 s 与自身进行 n 次拼接 | (2)(7) |
s[i] |
s 的第 i 项,起始为 0 | (3) |
s[i:j] |
s 从 i 到 j 的切片 | (3)(4) |
s[i:j:k] |
s 从 i 到 j 步长为 k 的切片 | (3)(5) |
len(s) |
s 的长度 | |
min(s) |
s 的最小项 | |
max(s) |
s 的最大项 | |
s.index(x[, i[, j]]) |
x 在 s 中首次出现项的索引号(索引号在 i 或其后且在 j 之前) | (8) |
s.count(x) |
x 在 s 中出现的总次数 |
列表list
list=[‘1’,’2’,’3’],可存放不同类型元素,支持多维列表
创建
list=[]
list=[1,2,3,4]
lx for x in iterable迭代器生成
list()转换
增
追加:append()函数
插入:insert(index, n)函数:将n插入index这个位置
删
按下标删除1:pop(index)函数,无参则删除末尾元素
按下标删除2:del listname[index],del indexname删除整个变量
按元素删除:remove(n)函数: n为list中的元素,并非index
改
改元素:list[index]=’xxx’
清空元素:clear()函数
合并列表:s.extend(list):将list的内容追加到s后面
反转列表:reverse()函数,反转元素
排序列表:sort()函数,对本函数进行原地排序
查
查位置:index()函数,元素返回所在下标
查内容:list(index),以下标查询元素内容
字典Dict
dic={“n1”:1, “n2”:”2”, “n3”:[13,4,5]}。键值对形式存在,key是唯一键,value可不同类型、可重复。键值对保留为插入时顺序
创建
- 空字典:dic={}
- 字典:dic={“n1”:’”1”, “m”:”2”}
- 字典推导式:
{x: x**2 for x in (2, 4, 6)}
- dict()转换:dict(spe=123, guido=456,jack=789)
增
dic[key]=value,直接添加
复制其他dic:copy()函数
删
删除指定kv:pop(key)函数,key必填,删除前返回value值
删除指定kv:del dic[key]:若key不存在则报错。
清空dic: clear()函数
改
更新dic的值:update()
修改指定key的值:dic[‘key’]=xxx
查
查字典长度:len(dic)函数
查是否存在:key in dic 或key not in dic
查所有key:items()函数
查所有value:values()函数
查指定value:get(key)函数
返回value,若没有则个返回默认值:setdefault(key,default)函数
其他
循环方式(1)同时获取键值对:for k, v in knights.items():print(k,v)
循环方式(2)获取指定键值对:for i,v in enumerate(['a', 'b', 'c']):print(i,v)
循环方式(3)多序列循环:
1 |
|
…………
元组
files = (“file1”, “file2”, “file3”),注意列表用[],元组用(),也可无需使用(),决定元组的是逗号而不是括号。
元组是不可变序列,元素定义初始化后不可更改。
增
tup=()
tup=2,3,4或tup=(2,3,4):此语法是一样的
tuple()函数转换
- 元组打包:tup=1,2,3
- 序列解包:x,y,z = tup,tup可分别赋值给x、y、z
查
查数量:len()
查位置:index(n)查询n所在下标
查指定元素:tup[index]
set集合
files = {“file1”, “file3”, “file5”} , set中的是无序、不重复的,常用于元素检测、消除重复元素、交集并集等操作。
创建
- 创建带元素的集合:files = {“file1”, “file3”, “file5”}
- 创建空集:a=set()
- 集合推导式:
{c for c in 'abracadabra' if c not in 'abc'}
- set()函数转换
增
add()函数 新增元素
删
set.remove(n):删除n元素
改
update()函数 更新
clear()清空
数学操作
交集:set.intersection(set1) 即&,获取共同存在的元素集合
并集:set.union(set1) 即 | ,获取两者所有元素(不重复)
补集:set.difference(set1) 即 - ,获取set中set1不存在的元素
函数
定义
1 |
|
传参
Python的参数传递既不是值传递也不是引用传递,而是赋值传递。参数传递时,Python让新变量与原变量指向了相同的对象。一个对象是可以被多个变量所指向的,也就是说一个参数传入函数后,会有另一个变量指向它
- 当参数为不可变对象时,所有指向该变量的值总是一样的,不会改变(改变之后是一个新对象)
- 当参数为可变对象时,在函数中修改时对影响所有指向该对象的变量
注意:
- 变量是可以被删除的,但对象无法被删除
- 要想在函数中改变外部传进来的参数,要么重新对其赋值,要么将其return
参数类型
- 必传参数:直接声明
- 关键字参数:传参时可设置参数名,防止乱序
function(parm1=0, parm2=1)
- 默认参数,调用时可选填:
def function(parm1, parm=1)
- 不定量参数,调用时可传入更多参数:
def function(parm1, *parm2)
匿名函数
lambda表达式创建,没有代码块,只有一个表达式sum = lambda parm1, parm2 : parm1 + parm2
冒号前表示输入参数,冒号后表示函数输出;
lambda:None
表示没有输入参数,且输出None
类
创建:
1 |
|
self
:在类中获取当前类的功能或属性
__init__()
:类被实例化时会自动调用__init__()
函数,用于初始化设置
继承
1 |
|
Chinese继承了Pepole类,继承了Pepole的函数和属性,在子类中可以复用Pepole的属性和函数,以减少公有属性或功能的开发
函数和属性的私有化
私有程度 | 介绍 |
---|---|
_ 一个下划线开头,如_age | 弱隐藏,不想让调用者使用。但若必须调用还是可以用的 |
__ 两个下划线开头,如__password | 强隐藏,不让调用者使用,自己在内部可以用 |
类的特殊方法
__new__()
;构造函数,用于创建对象
__init__()
类被实例化后自动调用,用于初始化实例对象,可被继承。若子类需要调用,需显式调用,以确保父类正确初始化
__repr__()
输出对象的字符串(正式值),返回的字符串准确、无歧义,尽可能表达出如何创建出来的这个对象
__str__()
输出对象的字符串(非正式值),返回的字符串可读性更高,使用更方便
__iter__()
创建迭代器时被调用,遍历序列时使用
__next__()
从容器中返回下一项
……
模块管理
如下多种引用方式:
1 |
|
编码风格
- 使用4个空格缩进,不使用制表符
- 一行代码不超过79字符
- 函数和类之间用空行分开
- 注释尽量单独放一行
- 函数、类明规则命名
- …………
目录管理
增
新增目录:os.mkdir()
,多级目录os.makedirs()
复制文件:shutil.copy2()
删
删除空目录:os.removedirs
删除目录及其所有子目录(需导入) :shutil.rmtree()
查
查看当前目录:os.getcmd()
、realpath
查看某文件所在的目录名:os.path.dirname()
查看当前目录下的文件列表os.listdir
查看文件或目录是否存在:os.path.exists()
查看是否是文件/目录:os.path.isfile()/isdir()
其他操作
切分文件全名中的目录和文件:os.path.split()
文件操作
脚本环境下获取当前工作区目录:os.path.split(os.path.realpath(__file__))[0]
命令环境下获取当前工作区目录:os.getcwd()
或os.path.abspath('.')
如果在只写模式中读取,或在只读模式中写入,会报io.UnsupportedOperation
错误
增
w
为写入模式,文件不存在则创建,文件已存在则直接会覆盖w+
为可读可写模式,不存在则创建,文件已存在则直接会覆盖a
为写入模式,文件不存在则创建,已存在则不覆盖,追加在文件末尾a+
可读可写,文件不存在则创建,已存在则不覆盖,追加在文件末尾
1 |
|
**with:**当使用with时,会自动调用类的__enter__()
,然后开始执行with下面的语句,执行结束后会自动调用__exit__()
**writelines:**传入列表格式的数据使用,会分行写入
删
1 |
|
查/改
r
为读取模式,文件不存在时会报FileNotFoundError
错误r+
为可读可写模式,文件不存在时会报FileNotFoundError
错误,写操作会覆盖
1 |
|
读写二进制
wb
&rb
为读写二进制数据,r
读取文件时,读到文档结束符(EOF)就算是读完了,但字节\x1A(26)
转成字符后就是文档结束符,因此使用r
可能会出现文档读取不全的现象。
- 使用
r
读取,read()
返回的是字符串数据 - 使用
rb
读取,read()
返回的是bytes数据
指定编码
1 |
|
异常处理
使用场景
在不确定某段代码是否能成功执行时,就需要使用异常处理。如文件读取、解析Json文件等,就需要用到FileNotFoundError
或者JSONDecodeError
等。
注意!
不能滥用异常,在流程控制的逻辑中,一般不用异常处理,如:
1 |
|
捕获单个异常
except
:捕获异常
1 |
|
捕获多个异常
注意:一般情况下难以保证程序覆盖所有异常类型,通常在最后一个except捕获一个Exception基类,这样就可以捕获任意非系统异常。或者直接写except捕获所有异常(包括系统异常)
except(Err1, Err2,Err3……)
1 |
|
- 使用多次except,单独处理
1 |
|
异常处理分支
try-except-else
:如果没有捕获到异常,则运行其他代码
1 |
|
try-except-finally
:不论是否捕获到异常,都需执行finnally
中的代码
1 |
|
自定义异常
自定义异常需要继承Eception基类,并定义初始化函数和str函数
1 |
|
手动抛出异常
raise
:提示代码中可能出现的异常,供他人调用时debug
1 |
|
可被raise的Error如下表:
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
Json序列化
内置模块pickle实现了Python对象的二进制序列化和反序列化。序列化即将对象及其层次结构转化为字节流的过程。
pickle
序列化对象
pickle.dumps()
:将对象序列化,并返回该对象的bytes类型数据
1 |
|
保存对象至文件
pickle.dump()
:将对象序列化并保存至本地
1 |
|
读取文件
pickle.load()
:将本地文件读取出来
1 |
|
注意:
- Pickle在反序列化类的时候需要有这个类的class,否则会找不到这个类二失败。
- 有些对象例如打开的文件、网络链接、线程进程等,如果将这些对象赋给class的属性上,就不能被打包,因为这些需要依赖外部系统状态。
Json
不需要转成二进制,在网络中传输相对安全
json.dumps()
和json.loads()
:将对象转化为json格式的字符串 & 将字符串转换为对象。
1 |
|
json.dump()
和json.load()
:与上面类似,一般与文件操作一起用
1 |
|
注意:json无法序列化class对象
对比 | Pickle | Json |
---|---|---|
存储格式 | Python 特定的 Bytes 格式 | 通用 JSON text 格式,可用于常用的网络通讯中 |
数据种类 | 类,功能,字典,列表,元组等 | 基本和 Pickle 一样,但不能存类,功能 |
保存后可读性 | 不能直接阅读 | 能直接阅读 |
跨语言性 | 只能用在 Python | 可以跨多语言读写 |
处理时间 | 长(需编码数据) | 短(不需编码) |
安全性 | 不安全(除非你信任数据源) | 相对安全 |
正则
正则常见字符
字符 | 描述 |
---|---|
\d | 代表任意数字,就是阿拉伯数字 0-9 这些玩意。 |
\D |
大写的就是和小写的唱反调,\d 你代表的是任意数字是吧?那么我 \D 就代表不是数字的。 |
\w |
代表字母,数字,下划线。也就是 a-z、A-Z、0-9、_。 |
\W |
跟 \w 唱反调,代表不是字母,不是数字,不是下划线的。 |
\n | 代表一个换行。 |
\r |
代表一个回车。 |
\f |
代表换页。 |
\t |
代表一个 Tab 。 |
\s |
代表所有的空白字符,也就是上面这个:\n、\r、\t、\f。 |
\S |
跟 \s 唱反调,代表所有不是空白的字符。 |
\A |
代表字符串的开始。 |
\Z |
代表字符串的结束。 |
^ | 匹配字符串开始的位置。 |
$ | 匹配字符创结束的位置。 |
. | 代表所有的单个字符,除了 \n \r |
[...] |
代表在 [] 范围内的字符,比如 [a-z] 就代表 a到z的字母 |
[^...] |
跟 […] 唱反调,代表不在 [] 范围内的字符 |
{n} | 匹配在 {n} 前面的东西,比如: o{2} 不能匹配 Bob 中的 o ,但是能匹配 food 中的两个o。 |
{n,m} |
匹配在 {n,m} 前面的东西,比如:o{1,3} 将匹配“fooooood”中的前三个o。 |
{n,} |
匹配在 {n,} 前面的东西,比如:o{2,} 不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。 |
* |
和 {0,} 一个样,匹配 * 前面的 0 次或多次。 比如 zo* 能匹配“z”、“zo”以及“zoo”。 |
+ |
和{1,} 一个样,匹配 + 前面 1 次或多次。 比如 zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。 |
? |
和{0,1} 一个样,匹配 ?前面 0 次或 1 次。 |
a|b | 匹配 a 或者 b。 |
() |
匹配括号里面的内容。 |
匹配字符串
例:
1 |
|
r
代表后面的字符串是一个正则
根据上表,\w
匹配字母数字下划线,+?
代表匹配多次
打印结果中的span=(0, 17)
表示找到的字符串在原始字符的位置,match
表示找到的具体字符串内容
正则除了search()
,还有其他功能:
功能 | 说明 | 举例 |
---|---|---|
re.search() | 扫描查找整个字符串,找到第一个模式匹配的 | re.search(rrun, I run to you) > ‘run’ |
re.match() | 从字符的最开头匹配,找到第一个模式匹配的即使用 re.M 多行匹配,也是从最最开头开始匹配 | re.match(rrun, I run to you) > None |
re.findall() | 返回一个不重复的 pattern 的匹配列表 | re.findall(rr[ua]n, I run to you. you ran to him) > [‘run’, ‘ran’] |
re.finditer() | 和 findall 一样,只是用迭代器的方式使用 | for item in re.finditer(rr[ua]n, I run to you. you ran to him): |
re.split() | 用正则分开字符串 | re.split(rr[ua]n, I run to you. you ran to him) > [‘I ‘, ‘ to you. you ‘, ‘ to him’] |
re.sub() | 用正则替换字符 | re.sub(rr[ua]n, jump, I run to you. you ran to him) > ‘I jump to you. you jump to him’ |
re.subn() | 和 sub 一样,额外返回一个替代次数 | re.subn(rr[ua]n, jump, I run to you. you ran to him) > (‘I jump to you. you jump to him’, 2) |
匹配HTML
1 |
|
-
.*?list_num.*?
这里的.*?
加在了量词*
的后面,使得该量词*
变为非贪婪模式,即匹配尽量少的字符。例如,对 “123abc” 使用/\d+/
将会匹配 “123”,而使用/\d+?/
则只会匹配到 “1”。- 在当前案例中,使用正则来匹配html字符串,大量使用
.*?
来匹配其他字符串。
- 在当前案例中,使用正则来匹配html字符串,大量使用
-
当前匹配模式为
re.S
,表示跨行匹配。将多行字符串当作一个整体,将换行符\n
当作一个普通字符加入这个整体中。 -
<span\sclass="price_n"
这里的\s
代表空白字符,正则中不允许有空格出现 -
建议在写长正则时,先将单个值的正则写出来,最后再拼起来,这样可以省去很多排错时间
-
如正则一直无法匹配,尝试查看源码是否存在该值。如下图这种a标签的内容是计算上去的,并非源码中提供。
匹配模式
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符,跨行匹配 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
迭代器,生成器与修饰器
迭代器
某对象实现了__iter__()
函数,且该函数返回一个迭代器对象,这个对象就可以成为可迭代对象。可以用for循环遍历的对象均是可迭代对象。
迭代器协议包括:
- 实现了
__next__()
函数 __next__()
函数返回了某个数值__next__()
取值完成后,抛出StopIteration
异常
生成器
用于在遍历大规模数据时使用的写法,避免内存中数据量过大。生成器调用__next__()
函数以惰性方式获取下一个值,遍历结束后无法再次遍历。
优势就在于边迭代边输出,提供了延迟操作。
(哪儿都没说明白,等用上了再说)
装饰器
装饰器的实现前提:函数也是对象,函数可以当做参数传入其他函数。函数也可以当做返回值被return
装饰器的作用就是为一个函数做额外的事情,如写日志、测试、鉴权等。装饰器一般在多个函数中做同样操作时发挥的作用最大,可以较大限度减少代码量
举例说明:
这里的mains函数上方添加了一行@dector
,将mains
函数作为参数传入了dector中。在dector
内部又调用了原函数mains(即参数func),但在调用前后分别执行输出了语句。这就是装饰器dector的作用,在不改变原函数行为的前提下,改变原函数的行为。
1 |
|
自定义参数、保留函数元信息
除了原函数所需要的参数,装饰器本身也可以定义参数,例如希望指定装饰器内部函数的执行次数,可以在装饰器这里传入。
需要注意的是,当同一个函数被包装器修饰后,它的名字就已经变成了包装器内部的函数(wrapper),如果需要改成原来的greet,在上面加上一个@functools.wraps(func)
就可以了,这会将原函数的元信息拷贝至对应的装饰器函数里。
1 |
|
装饰器的嵌套
允许有多个装饰器,执行顺序是从里到外(有待研究):
1 |
|
类装饰器
在myDecorator
类的__init__()
中定义和调用了aFunction
函数,在__init__()
执行结束后,aFunction
函数已经声明且调用完了。然后输出第三句输出。最后执行aFunction()
时,实际上是执行了myDecorator
的__call__()
方法。
因此,被装饰后的函数aFunction()
,已经是类myDecorator
的对象了,当再次调用aFunction()
时,也就是在调用类myDecorator
的对象,所以会调到__call__()
函数。
使用类装饰器来装饰函数来对函数添加一些额外的属性或功能时,一般会在类的__init__()
中传入函数,在__call__()
调用修饰的函数或者其他额外处理。
1 |
|
补充:
定义了__call__()
方法的类的对象可以像函数一样被调用,此时调用的是对象的__call__()
方法。因为按照装饰器语法的涵义,
1 |
|
进阶用法
lambda表达式
用于创建匿名函数,语法上限为单个表达式,是正常函数定义的语法糖。如下两种写法是一样的:
1 |
|
遍历缩写
如下写法是一样的。
1 |
|
分支缩写
对于简单逻辑,允许如下写法:
1 |
|
遍历简写
在for、if中使用简写
1 |
|
带计数器的序列:enumerate()函数
1 |
|
zip遍历
zip()将序列作为参数将其打包,可同时迭代多个序列
1 |
|
反转序列
1 |
|
conda使用
安装(略)
基本操作
创建独立的虚拟环境
1 |
|
查看当前虚拟环境列表
1 |
|
切换新建的test
环境
1 |
|
退出当前虚拟环境
1 |
|
删除指定虚拟环境
1 |
|
依赖迁移
在cmd或指定的本地路径下执行,导出依赖列表
1 |
|
将txt文件放置新项目位置,执行读取
1 |
|