Python高阶(三) - 我的Pythonic日记
2017-07-12 本文已影响57人
Spareribs
1. 循环遍历可迭代对象(in enumerate)
Non-Pythonic
# 基于索引的while循环
choices = ['red', 'green', 'blue']
i = 0
while i < len(choices):
print('{}) {}'.format(i, choices[i]))
i += 1
# 或者for循环:
choices = ['red', 'green', 'blue']
for i in range(len(choices)):
print('{}) {}'.format(i, choices[i]))
Pythonic
choices = ['red', 'green', 'blue']
for choice in choices:
print(choice)
# 加上序列的枚举
choices = ['red', 'green', 'blue']
for idx, choice in enumerate(choices):
print('{}) {}'.format(idx, choice))
2 (字典 集合 列表)推导式
Non-Pythonic
# 字典推导式
# 列表推导式
result = []
for i in range(10):
s = i 2
result.append(s)
Pythonic
# 列表推导式
[i2 for i in xrange(10)]
3 漂亮的打印出JSON
>>> import json
>>> print(json.dumps(data)) # No indention
{"status": "OK", "count": 2, "results": [{"age": 27, "name": "Oz", "lactose_intolerant": true}, {"age": 29, "name": "Joe", "lactose_intolerant": false}]}
>>> print(json.dumps(data, indent=2)) # With indention
{
"status": "OK",
"count": 2,
"results": [
{
"age": 27,
"name": "Oz",
"lactose_intolerant": true
},
{
"age": 29,
"name": "Joe",
"lactose_intolerant": false
}
]
}
4 异常捕获代替if判断
Non-Pythonic
if resource_exists():
use_resource()
Pythonic
try:
use_resource()
except ResourceDoesNotExist:
...
5 优雅的字典操作
Pythonic
# 读取键值,如果不存在不会抛出异常,直接返回Null
>>> dict().get('missing key', 'failover value')
'failover value'
# 设置默认值
>>> dict().setdefault('key', 'new value')
'new value'
>>> d = {'key': 'old value'}
>>> d.setdefault('key', 'new value')
'old value'
# 或自动生成缺少键的初始值:
>>> d = collections.defaultdict(int)
>>> d['missing key'] += 1
>>> d['missing key']
1
# 有序字典:
>>> d = collections.OrderedDict()
>>> d['x'] = 1
>>> d['y'] = 1
>>> list(d)
['x', 'y']
>>> del d['x']
>>> d['x'] = 1
>>> list(d)
['y', 'x']
6 上下文管理(with ** as ** )
Non-Pythonic
resource = allocate()
try:
resource.use()
finally:
resource.deallocate()
# 打开/关闭文件
f = open('data.txt')
try:
data = f.read()
finally:
f.close()
Pythonic
with allocate_resource() as resource:
resource.use()
# 打开/关闭文件
with open('data.txt') as f:
data = f.read()
- 最后一定不能忘记的操作是关闭文件,即使报错了也要 close。普通的方式是在 finnally 块中显示的调用 close 方法。
- 使用 with 语句,系统会在执行完文件操作后自动关闭文件对象。
7 装饰器
详细内容查看 Python高阶(二) - 按部就班了解装饰器
8 快速交换
Non-Pythonic
a = 1
b = 2
tmp = a
a = b
b = tmp
9 循环遍历区间元素(xrange)
Non-Pythonic
for i in [0, 1, 2, 3, 4, 5]:
print i
# 或者
for i in range(6):
print i
Pythonic
for i in xrange(6):
print i
10 带有索引位置的集合遍历(enumerate)
Non-Pythonic
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)):
print i, '--->', colors[i]
Pythonic
for i, color in enumerate(colors):
print i, '--->', color
11 字符串连接(join)
Non-Pythonic
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
s = names[0]
for name in names[1:]:
s += ', ' + name
print s
Pythonic
print ', '.join(names)
说明:
- join 方法整个过程只会产生一个字符串对象
- 使用+操作时,每执行一次+操作就会导致在内存中生成一个新的字符串对象
12 合理使用列表
Non-Pythonic
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
names.pop(0)
names.insert(0, 'mark')
Pythonic
from collections import deque
names = deque(['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie'])
names.popleft()
- 列表对象(list)是一个查询效率高于更新操作的数据结构,删除和插入需要对剩下的元素做移动操作
- deque 是一个双向队列的数据结构,删除元素和插入元素会很快
13 序列解包
Non-Pythonic
p = 'vttalk', 'female', 30, 'python@qq.com'
name = p[0]
gender = p[1]
age = p[2]
email = p[3]
Pythonic
name, gender, age, email = p
14 遍历字典的 key 和 value
Non-Pythonic
# 方法一
for k in d:
print k, '--->', d[k]
# 方法二
for k, v in d.items():
print k, '--->', v
Pythonic
for k, v in d.iteritems():
print k, '--->', v
15 链式比较操作
Non-Pythonic
age = 18
if age > 18 and x < 60:
print("yong man")
Pythonic
if 18 < age < 60:
print("yong man")
16 行内判断 if/else 三目运算
Non-Pythonic
if gender == 'male':
text = '男'
else:
text = '女'
Pythonic
text = '男' if gender == 'male' else '女'
17 真值判断
Non-Pythonic
if attr == True:
do_something()
if len(values) != 0: # 判断列表是否为空
do_something()
Pythonic
if attr:
do_something()
if values:
do_something()
18 for/else语句
Non-Pythonic
flagfound = False
for i in mylist:
if i == theflag:
flagfound = True
break
process(i)
if not flagfound:
raise ValueError("List argument missing terminal flag.")
Pythonic
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("List argument missing terminal flag.")
- for else 是 Python 中特有的语法格式,else 中的代码在 for 循环遍历完所有元素之后执行。
19 字符串格式化
Non-Pythonic
s1 = "foofish.net"
s2 = "vttalk"
s3 = "welcome to %s and following %s" % (s1, s2)
Pythonic
s3 = "welcome to {blog} and following {wechat}".format(blog="foofish.net", wechat="vttalk")
20 列表切片
Non-Pythonic
items = range(10)
# 奇数
odd_items = []
for i in items:
if i % 2 != 0:
odd_items.append(i)
# 拷贝
copy_items = []
for i in items:
copy_items.append(i)
Pythonic
# 第1到第4个元素的范围区间
sub_items = items[1:4]
# 奇数
odd_items = items[1::2]
#拷贝
copy_items = items[::] 或者 items[:]
解释:
列表元素的下标不仅可以用正数表示,还是用负数表示,最后一个元素的位置是 -1,从右往左,依次递减。
P | y | t | h | o | n |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 |
-6 | -5 | -4 | -3 | -2 | -1 |
21 善用生成器
Non-Pythonic
def fib(n):
a, b = 0, 1
result = []
while b < n:
result.append(b)
a, b = b, a+b
return result
Pythonic
def fib(n):
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
生成器的好处就是无需一次性把所有元素加载到内存,只有迭代获取元素时才返回该元素
22 用Counter来计数
Non-Pythonic
# Non-pythonic, ugly
x_list = ['Ozil', 'Ramsey', 'Ozil', 'Ramsey', 'Giroud']
x_dict = {}
for x in x_list:
if x in x_dict.keys():
x_dict[x] += 1
else:
x_dict[x] = 1
print(x_dict)
Pythonic
#Pythonic, elegant
from collections import Counter
x_list = ['Ozil', 'Ramsey', 'Ozil', 'Ramsey', 'Giroud']
x_dict = Counter(x_list)
print(x_dict)