30个有关Python的小技巧,给程序员的 30 个基本 Python 贴士与技巧 30个有关Python的小技巧 给程序员的 30 个基本 Python 贴士与技巧
从我开始学习python的时候,我就开始自己总结一个python小技巧的集合。后来当我什么时候在Stack Overflow
或者在某个开源软件里看到一段很酷代码的时候,我就很惊讶:原来还能这么做!,当时我会努力的自己尝试一下这段代码,直到我懂了它的整体思路以后,我就把这段代码加到我的集合里。这篇博客其实就是这个集合整理后一部分的公开亮相。如果你已经是个python大牛,那么基本上你应该知道这里面的大多数用法了,但我想你应该也能发现一些你不知道的新技巧。而如果你之前是一个c,c++,java的程序员,同时在学习python,或者干脆就是一个刚刚学习编程的新手,那么你应该会看到很多特别有用能让你感到惊奇的实用技巧,就像我当初一样。
每一个技巧和语言用法都会在一个个实例中展示给大家,也不需要有其他的说明。我已经尽力把每个例子弄的通俗易懂,但是因为读者对python的熟悉程度不同,仍然可能难免有一些晦涩的地方。所以如果这些例子本身无法让你读懂,至少这个例子的标题在你后面去google搜索的时候会帮到你。
整个集合大概是按照难易程度排序,简单常见的在前面,比较少见的在最后。
1.1 拆箱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
3
c
)
]
c
)
)
c
)
]
a
1
b
2
c
3
d
4
|
1.2 拆箱变量交换
1
2
3
4
|
2
a
b
)
|
1.3 扩展拆箱(只兼容python3)
1
2
3
4
5
6
7
|
]
a
1
b
]
c
5
|
1.4 负数索引
1
2
3
4
5
|
]
]
10
]
8
|
1.5 切割列表
1
2
3
|
]
]
]
|
1.6 负数索引切割列表
1
2
3
|
]
]
]
|
1.7指定步长切割列表
1
2
3
4
5
6
7
|
]
]
]
]
]
]
]
|
1.8 负数步长切割列表
1
2
3
4
5
|
]
]
]
]
]
|
1.9 列表切割赋值
1
2
3
4
5
6
7
8
9
10
|
]
]
a
]
]
a
]
]
a
]
|
1.10 命名列表切割方式
1
2
3
4
5
6
|
]
)
LASTTHREE
)
]
]
|
1.11 列表以及迭代器的压缩和解压缩
1
2
3
4
5
6
7
|
]
]
)
z
]
)
]
|
1.12 列表相邻元素压缩器
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
|
]
)
]
)
)
]
)
]
)
]
)
]
)
]
)
)
]
)
]
)
]
|
1.13 在列表中用压缩器和迭代器滑动取值窗口
1
2
3
4
5
6
7
8
9
10
11
|
:
]
)
.
]
)
]
)
]
)
]
|
1.14 用压缩器反转字典
1
2
3
4
5
6
7
8
|
}
)
]
)
]
)
mi
}
|
1.15 列表展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
]
)
]
)
]
]
]
]
]
]
]
]
)
]
|
1.16 生成器表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
|
)
)
0
)
1
)
4
)
9
)
2025
)
408
|
1.17 字典推导
1
2
3
4
5
6
7
|
}
m
}
}
m
}
|
1.18 用字典推导反转字典
1
2
3
4
5
|
}
m
}
}
}
|
1.19 命名元组
1
2
3
4
5
6
7
8
|
)
)
p
)
x
1.0
y
2.0
|
1.20 继承命名元组
1
2
3
4
5
6
7
8
9
|
:
)
:
)
.
)
)
q
)
|
1.21 操作集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
}
A
)
}
B
)
B
)
B
)
B
)
A
)
B
)
)
True
|
1.22 操作多重集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
)
)
A
)
B
)
B
)
B
)
B
)
B
)
A
)
|
1.23 统计在可迭代器中最常出现的元素
1
2
3
4
5
6
7
|
)
A
)
)
]
)
]
|
1.24 两端都可操作的队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
)
)
)
)
)
Q
)
)
4
)
6
Q
)
)
Q
)
)
Q
)
|
1.25 有最大长度的双端队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
)
:
)
)
.
0
1
2
3
4
5
6
7
8
9
|
1.26 可排序词典
1
2
3
4
5
6
7
8
9
|
)
)
8
)
)
9
)
)
1
|
1.27 默认词典
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
)
]
:
>
'a'
>>>
)
]
0
]
0
)
]
''
'a'
]
'a'
)
]
'[default value]'
]
'[default value]'
|
1.28 默认字典的简单树状表达
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
|
json
)
)
'file'
'File'
'New'
'new();'
'Open'
'open();'
'Close'
'close();'
)
{
{
,
{
{
,
,
{
,
,
{
,
}
,
}
}
|
1.29 对象到唯一计数的映射
1
2
3
4
5
6
7
8
9
10
11
12
|
collections
)
]
0
]
1
]
2
]
0
]
1
|
1.30 最大和最小的几个列表元素
1
2
3
4
5
|
]
)
]
)
]
|
1.31 两个列表的笛卡尔积
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
|
:
)
)
)
)
)
)
:
)
.
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
|
1.32 列表组合和列表元素替代组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
:
)
.
123
124
125
134
135
145
234
235
245
345
:
)
.
11
12
13
22
23
33
|
1.33 列表元素排列组合
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
|
:
)
.
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
|
1.34 可链接迭代器
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
|
]
:
p
.
)
)
)
)
)
)
)
)
)
)
)
subset
.
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
|
1.35 根据文件指定列类聚
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
itertools
:
]
.
]
:
'
'.join(' '.join('{: <16}'.format(s) for s in row) for row in rows)
.
)
none
soft
none
hard
none
soft
none
hard
none
soft
none
hard
none
soft
none
none
none
none
none
hard
none
soft
none
none
)
:
'-----------'
value
)
.
-
hard
hard
hard
hard
hard
-
none
none
none
none
none
none
none
none
none
none
none
none
none
none
none
none
-
soft
soft
soft
soft
soft
soft
|
给程序员的 30 个基本 Python 贴士与技巧
贴士#1. 原地交换两个数字
Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例:
1
2
3
4
5
6
7
8
|
20
)
x
)
#1 (10, 20)
#2 (20, 10)
|
赋值的右侧形成了一个新的元组,左侧立即解析(unpack)那个(未被引用的)元组到变量 <a>
和 <b>
。
一旦赋值完成,新的元组变成了未被引用状态并且被标记为可被垃圾回收,最终也完成了变量的交换。
贴士#2. 链状比较操作符
比较操作符的聚合是另一个有时很方便的技巧:
1
2
3
4
5
6
7
8
9
10
|
10
20
)
# True
9
)
# False
|
贴士#3. 使用三元操作符来进行条件赋值
三元操作符是 if-else 语句也就是条件操作符的一个快捷方式:
1
|
]
|
这里给出几个你可以用来使代码紧凑简洁的例子。下面的语句是说“如果 y 是 9,给 x 赋值 10,不然赋值为 20”。如果需要的话我们也可以延长这条操作链。
1
|
20
|
同样地,我们可以对类做这种操作:
1
|
)
|
在上面的例子里 classA 与 classB 是两个类,其中一个类的构造函数会被调用。
下面是另一个多个条件表达式链接起来用以计算最小值的例子:
1
2
3
4
5
6
7
8
9
10
|
:
)
)
)
)
)
#Output
#0 #1 #2 #3
|
我们甚至可以在列表推导中使用三元运算符:
1
2
3
|
]
#=> [0, 1, 16, 81, 256, 625, 1296, 2401, 4096, 6561, 10000, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401]
|
贴士#4. 多行字符串
基本的方式是使用源于 C 语言的反斜杠:
1
2
3
4
5
|
)
# select * from multi_row where row_id < 5
|
另一个技巧是使用三引号:
1
2
3
4
5
6
|
)
#select * from multi_row
#where row_id < 5
|
上面方法共有的问题是缺少合适的缩进,如果我们尝试缩进会在字符串中插入空格。所以最后的解决方案是将字符串分为多行并且将整个字符串包含在括号中:
1
2
3
4
5
6
|
)
)
#select * from multi_row where row_id < 5 order by age
|
贴士#5. 存储列表元素到新的变量中
我们可以使用列表来初始化多个变量,在解析列表时,变量的数目不应该超过列表中的元素个数:【译者注:元素个数与列表长度应该严格相同,不然会报错】
1
2
3
4
5
6
|
]
testList
)
#-> 1 2 3
|
贴士#6. 打印引入模块的文件路径
如果你想知道引用到代码中模块的绝对路径,可以使用下面的技巧:
1
2
3
4
5
6
7
8
|
threading
socket
)
)
#1- <module 'threading' from '/usr/lib/python2.7/threading.py'>
#2- <module 'socket' from '/usr/lib/python2.7/socket.py'>
|
贴士#7. 交互环境下的 “_” 操作符
这是一个我们大多数人不知道的有用特性,在 Python 控制台,不论何时我们测试一个表达式或者调用一个方法,结果都会分配给一个临时变量: _
(一个下划线)。
1
2
3
4
5
6
|
1
3
_
3
_
3
|
“_” 是上一个执行的表达式的输出。
贴士#8. 字典/集合推导
与我们使用的列表推导相似,我们也可以使用字典/集合推导,它们使用起来简单且有效,下面是一个例子:
1
2
3
4
5
6
7
8
|
}
}
)
)
#set([0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
#{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
|
注:两个语句中只有一个 <:>
的不同,另,在 Python3 中运行上述代码时,将 <xrange>
改为 <range>
。
贴士#9. 调试脚本
我们可以在 <pdb>
模块的帮助下在 Python 脚本中设置断点,下面是一个例子:
1
2
|
pdb
)
|
我们可以在脚本中任何位置指定 <pdb.set_trace()>
并且在那里设置一个断点,相当简便。
贴士#10. 开启文件分享
Python 允许运行一个 HTTP 服务器来从根路径共享文件,下面是开启服务器的命令:
# Python 2
1
|
SimpleHTTPServer
|
# Python 3
1
|
server
|
上面的命令会在默认端口也就是 8000 开启一个服务器,你可以将一个自定义的端口号以最后一个参数的方式传递到上面的命令中。
贴士#11. 检查 Python 中的对象
我们可以通过调用 dir() 方法来检查 Python 中的对象,下面是一个简单的例子:
1
2
|
]
)
|
1
|
]
|
贴士#12. 简化 if 语句
我们可以使用下面的方式来验证多个值:
1
|
:
|
而不是:
1
|
:
|
或者,对于 in
操作符我们也可以使用 '{1,3,5,7}'
而不是 '[1,3,5,7]'
,因为 set
中取元素是 O(1) 操作。
贴士#13. 运行时检测 Python 版本
当正在运行的 Python 低于支持的版本时,有时我们也许不想运行我们的程序。为达到这个目标,你可以使用下面的代码片段,它也以可读的方式输出当前 Python 版本:
1
2
3
4
5
6
7
8
9
10
|
sys
#Detect the Python version currently in use.
:
)
)
)
#Print Python version in a readable format.
)
|
或者你可以使用 sys.version_info >= (3, 5)
来替换上面代码中的 sys.hexversion != 50660080
,这是一个读者的建议。
在 Python 2.7 上运行的结果:
1
2
3
4
5
6
7
|
)
linux
3.5
3.5.
|
在 Python 3.5 上运行的结果:
1
2
3
4
5
6
|
)
linux
)
]
|
贴士#14. 组合多个字符串
如果你想拼接列表中的所有记号,比如下面的例子:
1
|
]
|
现在,让我们从上面给出的列表元素新建一个字符串:
1
|
)
|
贴士#15. 四种翻转字符串/列表的方式
# 翻转列表本身
1
2
3
4
5
|
]
)
)
#-> [5, 3, 1]
|
# 在一个循环中翻转并迭代输出
1
2
3
4
5
6
|
:
)
#1-> 5
#2-> 3
#3-> 1
|
# 一行代码翻转字符串
1
|
]
|
输出为 “nohtyP tseT”
# 使用切片翻转列表
1
|
]
|
上面的命令将会给出输出 [5,3,1]。
贴士#16. 玩转枚举
使用枚举可以在循环中方便地找到(当前的)索引:
1
2
3
4
5
6
7
|
]
:
)
#1-> 0 : 10
#2-> 1 : 20
#3-> 2 : 30
|
贴士#17. 在 Python 中使用枚举量
我们可以使用下面的方式来定义枚举量:
1
2
3
4
5
6
7
8
9
10
11
12
|
:
)
)
)
)
)
#1-> 0
#2-> 1
#3-> 2
#4-> 3
|
贴士#18. 从方法中返回多个值
并没有太多编程语言支持这个特性,然而 Python 中的方法确实(可以)返回多个值,请参见下面的例子来看看这是如何工作的:
1
2
3
4
5
6
7
8
9
10
|
# function returning multiple values.
:
4
# Calling the above function.
)
)
#-> 1 2 3 4
|
贴士#19. 使用 *
运算符(splat operator)来 unpack 函数参数
*
运算符(splat operator)提供了一个艺术化的方法来 unpack 参数列表,为清楚起见请参见下面的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:
)
}
]
)
)
)
#1-> x y z
#2-> 1 2 3
#3-> 10 20 30
|
贴士#20. 使用字典来存储选择操作
我们能构造一个字典来存储表达式:
1
2
3
4
5
6
7
8
9
10
|
{
,
y
}
)
)
#1-> 12
#2-> 6
|
贴士#21. 一行代码计算任何数的阶乘
Python 2.x.
1
2
3
4
|
)
)
#-> 6
|
Python 3.x.
1
2
3
4
5
|
functools
)
)
#-> 6
|
贴士#22. 找到列表中出现最频繁的数
1
2
3
4
|
]
)
#-> 4
|
贴士#23. 重置递归限制
Python 限制递归次数到 1000,我们可以重置这个值:
1
2
3
4
5
6
7
8
9
10
|
sys
1001
)
)
)
#1-> 1000
#2-> 1001
|
请只在必要的时候采用上面的技巧。
贴士#24. 检查一个对象的内存使用
在 Python 2.7 中,一个 32 比特的整数占用 24 字节,在 Python 3.5 中利用 28 字节。为确定内存使用,我们可以调用 getsizeof
方法:
在 Python 2.7 中
1
2
3
4
5
|
sys
1
)
#-> 24
|
在 Python 3.5 中
1
2
3
4
5
|
sys
1
)
#-> 28
|
贴士#25. 使用 __slots__
来减少内存开支
你是否注意到你的 Python 应用占用许多资源特别是内存?有一个技巧是使用 __slots__
类变量来在一定程度上减少内存开支。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
sys
:
:
files
folders
devices
)
:
]
:
files
folders
devices
)
#In Python 3.5
#1-> 1016
#2-> 888
|
很明显,你可以从结果中看到确实有内存使用上的节省,但是你只应该在一个类的内存开销不必要得大时才使用 __slots__
。只在对应用进行性能分析后才使用它,不然地话,你只是使得代码难以改变而没有真正的益处。
【译者注:在我的 win10 python2.7 中上面的结果是:
1
2
3
|
#In Python 2.7 win10
#1-> 896
#2-> 1016
|
所以,这种比较方式是不那么让人信服的,使用 __slots__
主要是用以限定对象的属性信息,另外,当生成对象很多时花销可能会小一些,具体可以参见 python 官方文档:
The slots declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because dict is not created for each instance. 】
贴士#26. 使用 lambda 来模仿输出方法
1
2
3
4
5
|
sys
)
)
#-> python tips 1000 1001
|
贴士#27. 从两个相关的序列构建一个字典
1
2
3
4
5
6
|
)
)
)
#-> {1: 10, 2: 20, 3: 30}
|
贴士#28. 一行代码搜索字符串的多个前后缀
1
2
3
4
5
|
)
)
#1-> True
#2-> True
|
贴士#29. 不使用循环构造一个列表
1
2
3
4
5
|
itertools
]
)
#-> [-1, -2, 30, 40, 25, 35]
|
贴士#30. 在 Python 中实现一个真正的 switch-case 语句
下面的代码使用一个字典来模拟构造一个 switch-case。
1
2
3
4
5
6
7
8
9
10
|
:
)
}
)
)
#1-> None
#2-> 2
|
结语 – 给程序员的基本 Python 贴士与技巧
我们希望上述的基本的 Python 贴士与技巧可以帮助你快速地 & 有效地完成任务,你可以在作业与项目中使用他们。
听从你的回馈会使我们变得更好,所以请分享你的想法。
你甚至可以要求我们写一个你选择的话题,我们会将其加入到我们的写作列表中。【*】
最后,如果你喜欢这个文章,请在社交媒体上分享给你的朋友。
坚持学习,