强烈建议在
Jupyter
中调试运行
以下一个代码块为一个Cell
文章内容较多情况下建议Ctrl+f
/Command+f
查询跳转,或目录概览
参考书籍 & 资料:
《Python编程快速上手》
《Python基础教程(第三版)》
《Python标准库参考》
随笔
字符串对齐格式的运用
# 一个非常棒的想法 |
dict 关于copy & deepcopy
# 浅拷贝时,复制字典项,字典值仍指向原件`p |
True
True
False
True
正则表达式
简单匹配一个密码,未对特殊字符的存在做判断
import re |
False
True
True
?: 可不捕获当前括号的内容
## 正则表达式 ?: 可不捕获当前括号的内容 |
Chapter
12
匹配对象和编组
在模块re中,查找与模式匹配的子串的函数都在找到时返回MatchObject对象。这种对象包 含与模式匹配的子串的信息,还包含模式的哪部分与子串的哪部分匹配的信息。这些子串部分称 为编组(group)。
编组就是放在圆括号内的子模式,它们是根据左边的括号数编号的,其中编组0指的是整个模式。
# 下面分组[1]为第一个括号(最左侧的括号) |
‘2’
引发异常
raise Exception()/NameError()/TypeError()/ValueError()...
可控制程序引发异常,以下是一段示例
number = int(input()) |
-1
———————————————————-
Exception Traceback (most recent call last)in
1 number = int(input())
2 if number < 0:
—-> 3 raise Exception(‘Number should be greater than 2’)
4 print(number + 1)
Exception: Number should be greater than 2
断言assert
其运行机制与if [not true]: raise Exception()
很像,引发AssertionError
def always_error(): |
sys.argv
返回的参数与命令行运行文件时文件名及其之后的参数一致
import sys |
命令行下运行
python3 get_argv.py first second third,fourth |
[‘get_argv.py’, ‘first’, ‘second’, ‘third,fourth’]
可以看到第一个参数为文件名,之后的参数以空格
分割,而非,
通过带星号的参数优雅的处理参数过多
def add(x,y,*others): |
输入的参数过多,只对前两个进行计算
3
查看作用域
vars() & locals() 皆可查看当前作用域
但注意,在函数内进行修改似乎并不能改变当时局部变量的值
def test(): |
{‘b’: 2}
2
Tips: globals() 可查看全局作用域,并可以在函数内修改,在函数内使用global
关联全局变量时,对其做的操作会影响到全局变量
关于 iterable对象
能一次返回其中一个成员的对象
检测一个对象是否是iterable 的唯一可信赖的方法是调用 iter(obj)
map() & filter() & reduce()
map() 和 filter() 基本都可通过列表推导 (List Comprehension) 替代实现
引用摘自Python标准库参考
,务必先有iterable概念再去理解,或者跳过看后面
map()
map(function, iterable, …)
返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器。如果传入了额外的 iterable 参数,function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。
以列表为例,翻译一下就是对list对象中的每个元素调用function,最终返回一个iterable对象,可以通过list()将其变为list对象
list(map(str, range(10))) # 等价于[str(i) for i in range(10)] |
[‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’]
filter()
filter(function, iterable)
用 iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支 持迭代的容器,或一个迭代器。如果 function 是 None ,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。
filter() 如其名,当成对iterable对象对过滤器理解即可,对对象中的每个元素调用function函数,返回其中结果为真的那些元素,若function=None,则过滤掉本身是假的元素
list(filter(None,[1,2,'',0,[],{},3,4])) # 等价于[i for i in [1,2,'',0,[],{},3,4] if i] |
[1,2,3,4]
reduce()
reduce(function, iterable[, initializer ])
将两个参数的 function 从左至右积累地应用到 iterable 的条目,以便将该可迭代对象缩减为单一的值。例如,reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 是计算 ((((1+2)+3)+4)+5) 的值。左边的参数 x 是积累值而右边的参数 y 则是来自 iterable 的更新值
求多个集合的并集时可使用 reduce(),需要先从functools中导入
from functools import reduce |
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
lambda 匿名内联函数
语法为: lambda [参数]: [表达式]
可与map(), filter(), reduce() 结合使用
获取函数运行时间和内存使用情况
内存的查看需要安装memory_profiler
包,pip install 即可
import memory_profiler |
生成器 generator
The value of a yield expression is None, until the program calls the method send(value).
yield表达式返回 None,直到使用 send(value) 方法
先看看生成器和函数在运行时的浅显差异
def my_gen(i): |
在以下调用 next() 和 send() 的所有位置设置断点,选择步入。下面的序号解释对应代码块中注释的语句:
- 可以发现并没有触发函数的if语句,在执行 yield 语句后 函数 便返回值了,注意,此时 yield 表达式并没有返回值给 value,在下一次运行时才会返回
- 此时会续上之前 yield ,像是被挂起的进程又被 next() 唤醒,并给 value 赋值,从 i += 1 往下运行,经过循环回到开头,然后遇到 yield 再次被挂起
- 注意,此时并没有从头开始,而是像唤醒进程一样继续,但是,你会发现生成器内部 yield 返回给 value 的值变成了10,这个值刚好是 send() 从外部发送的值,但你在一开始其实并没有执行 yield,若你有些困惑,不妨看看 1 注释
# 注意在同一行使用多个next时可能会发生一开始没有想到的结果 |
第一次 next() 运行结果:
2
第二次 next() 运行结果:
调用next()时 yield 返回值为 None
3
调用send(value) yield 返回值为 10
4
相关链接&图片:
双端队列
队列长度较短的情况下,使用 appendleft(x) 和 insert(0, x) 在队首插入元素的效率差不多,较长的情况下 appendleft 略优于 insert,测试用例:
import time |
【INSERT】: 1.208339929580688 s
【APPENDLEFT】0.8946981430053711s
对比队列(即列表)操作
注意,列表的 insert() 操作每次将会引起O(n)的内存移动,而双端队列对其进行了优化。在队首插入大量元素时,列表所消耗的时间远远大于双端队列,测试用例:
import time |
【双端队列】: 0.01209402084350586 s
【队列】: 1.6215879917144775 s
如果进程使用了局部变量,则可能导致另一个进程卡死
我在PyQt5中使用多进程并行操作时,因为调用了self.func(),致使UI界面卡死,而当我把该调用移到外部然后传递参数后,一切如预期进行。
导入 Python 包
导入包不代表导入了包中的函数,仅代表导入__init__.py中定义的函数,
利用 try 减少多余操作
if 'Tom' in person: |
上面这段代码查找了两次Tom
键,可以利用try的特性假设Tom
存在直接赋值
try: |
循环遍历嵌套字典的坑
当字典是多重嵌套时,比如request请求翻译返回的json,如果用 for i in json[‘trans_result’] 遍历时仅指定第一层的键,那么返回的值仅是它本身的字符串,而非内部嵌套结构,不过应该可以通过重写方法__iter__()
进行修改
报错:The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
if __name__ == '__main__': |
进程之间的通信队列
需要使用multiprocessing.Manager().Queue(),queue.Queue()用于多线程
m = multiprocessing.Manager() |
项目
Python 编程快速上手
9.4:将美国风格的日期文件改成欧洲风格
MM-DD-YYYY
->DD-MM-YYYY
#! python3 |
# Create regex and replace MM <-> DD |
9.5: 打包文件夹
## 打包文件,基于Python标准库 |
该链接可加深
shutil.make_archive()
理解
import os, shutil |
11.1 通过命令行进行谷歌地图检索
#! python3 |
关于
urllib.parse
模块
#! python3 |
/%E4%B8%AD%E5%9B%BD
%2F%E4%B8%AD%E5%9B%BD
b’/\xe4\xb8\xad\xe5\x9b\xbd’