1. 路径操作
比起os模块的path方法,python3标准库的pathlib模块的Path处理起路径更加的容易。
l例如:获取当前文件路径。
os版:1
2print(os.path.dirname(__file__))
print(os.getcwd())
pathlib版:1
print(pathlib.Path.cwd())
看着好像没啥区别,然后看下面这个。
获取上两级文件目录
os版:1
print(os.path.dirname(os.path.dirname(os.getcwd())))
pathlib版:1
print(pathlib.Path.cwd().parent.parent)
拼接路径
os版:1
print(os.path.join(os.path.dirname(os.path.dirname(os.getcwd())),"yamls","a.yaml"))
pathlib版:1
2parts=["yamls","a.yaml"]
print(pathlib.Path.cwd().parent.parent.joinpath(*parts))
运行时拼接路径
os版:1
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'yamls',f'{site_name}.yaml')
pathlib版:1
2parts=["yamls","a.yaml"]
print(pathlib.Path(__file__).resolve().parent.parent.joinpath(*parts))
另外pathlib生成的是个对象,在open文件操作中可以直接运行的但是如果当作字符串操作会出现错误,此时需要对其进行转换,使用os.fspath()即可,不过一般很少有操作路径字符串的习惯。
综合起来,还是pathlib拼接路径方便。
2. 保存标准格式的yaml文件
编程免不了要写配置文件,怎么写配置也是一门学问。
YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。
YAML在python语言中有PyYAML安装包。
前提安装第三方库1
2pip install pyaml
pip install ruamel.yaml
关于yaml的读取知识网上一堆了我就不说了,这里主要说写入。1
2
3
4from ruamel import yaml
data={"age":23,"sex":"男","name":"牛皮"}
with open(conf_file, "w", encoding='utf-8') as fs:
yaml.dump(data, fs, Dumper=yaml.RoundTripDumper, allow_unicode=True)
yaml写文件和json一样也是使用dump。
3. 同时迭代两个列表
以前的时候我是这么解决的1
2
3
4
5
6
7
8
9a = ["a", "b", "c", "d"]
b = [1, 2, 3] # 空的补充None
for index, a_item in enumerate(a):
b_item = None
if len(b) - 1 <= index:
pass
else:
b_item = b[index]
print({a_item:b_item})
现在通过itertools标准库的zip升级版zip_longest解决,可以通过fillvalue参数补充缺失值。当然如果比较的元素个数相同可以直接用zip。1
2
3
4
5
6from itertools import zip_longest
a = ["a", "b", "c", "d","e"]
b = [1, 2, 3] # 空的补充None
for a_item, b_item in zip_longest(a,b,fillvalue=0):
print({a_item:b_item})
4. 三元表达式还能这么用?
一般的我们这样写1
2a="hello" if 2>1 else "bye"
print(a)
我们知道python中false实际式0,true是1,所以对于上面的式子我们就可以这么写了。1
2a=["hello","bye"][2<1]
print(a)
因为2<1是false也就是0,所以输出了第一个元素hello。
5.简单的类使用namedtuple代替
先来一个简单的例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import collections
# Person=collections.namedtuple('Person','name age')
# 如果使用python中的关键字会出现错误,此时使用rename字段。
# 按照元素在元组中的下标赋值。class就是_2,def是_3
Person = collections.namedtuple('Person', ['name', 'age', 'class', 'def', 'name', 'name'], rename=True)
p = Person(name='lisa', age='12', _2="class2", _3="def", _4="name2", _5="name3")
print(p)
# 如果出现相同的字段第二次出现的时候也是用其下标,参考上面的例子。
# _fields查看字段名,可以发现内置模块和重复的字段标记为_加下标的形式
print(p._fields)
# 使用_asdict将namedtuple转为OrderedDict。
od = p._asdict()
print(od)
# 然后可以转为字典
print(dict(od))
# _replace()方法构建一个新实例,因为namedtuple是不可变类型所以这个方法可以返回一个新的对象。
new_p = p._replace(name="samJ")
print(new_p)
print(new_p is p) # 可以看到不是同一个对象。
一个实用的例子pyppeteer的例子感受下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36import asyncio
import pyppeteer
from collections import namedtuple
Response = namedtuple("rs", "title url html cookies headers history status")
async def get_html(url, timeout=30):
# 默认30s
browser = await pyppeteer.launch(headless=True, args=['--no-sandbox'])
page = await browser.newPage()
res = await page.goto(url, options={'timeout': int(timeout * 1000)})
data = await page.content()
title = await page.title()
resp_cookies = await page.cookies()
resp_headers = res.headers
resp_history = None
resp_status = res.status
response = Response(title=title, url=url,
html=data,
cookies=resp_cookies,
headers=resp_headers,
history=resp_history,
status=resp_status)
return response
if __name__ == '__main__':
url_list = ["http://www.10086.cn/index/tj/index_220_220.html", "http://www.10010.com/net5/011/",
"http://python.jobbole.com/87541/"]
task = (get_html(url) for url in url_list)
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*task))
for res in results:
print(res.title)
6 使用枚举让数字变得更易懂。
1 | import enum |
7 链式合并字典chainmap的使用
1 | from collections import ChainMap |
8 在不打乱列表顺序的基础上插入元素
1 | import bisect |
9 关于字典的逻辑运算你了解多少
1 | # 使用&操作符查看字典的相同之处 |
10 给切片起个名字
1 | a="safr3.14" |
11 获取出现频率高的元素
1 | from collections import Counter |