爬虫进化日记

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()
  1. 最后一定不能忘记的操作是关闭文件,即使报错了也要 close。普通的方式是在 finnally 块中显示的调用 close 方法。
  2. 使用 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)

说明:

  1. join 方法整个过程只会产生一个字符串对象
  2. 使用+操作时,每执行一次+操作就会导致在内存中生成一个新的字符串对象

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()
  1. 列表对象(list)是一个查询效率高于更新操作的数据结构,删除和插入需要对剩下的元素做移动操作
  2. 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.")
  1. 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)
上一篇下一篇

猜你喜欢

热点阅读