没错我要Pythonic

Pythonic

Posted by 淼淼淼 on August 29, 2018

Pythonic记录(转)


循环遍历可迭代对象(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))

列表推导式

  • Non-Pythonic
# 列表推导式
result = []
for i in range(10):
    s = i  2
    result.append(s)
  • Pythonic
# 列表推导式
[i2 for i in xrange(10)]

漂亮的打印出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
    }
  ]
}

异常捕获代替if判断

  • Non-Pythonic
if resource_exists():
    use_resource()
  • Pythonic
try:
    use_resource()
except ResourceDoesNotExist:
    ...

优雅的字典操作

  • 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']

上下文管理(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 语句系统会在执行完文件操作后自动关闭文件对象

装饰器

  • 由于内容较多,我将用一篇博文专门介绍

字符串连接(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 方法整个过程只会产生一个字符串对象 使用+操作时,每执行一次+操作就会导致在内存中生成一个新的字符串对象

合理使用列表

  • 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 是一个双向队列的数据结构,删除元素和插入元素会很快

序列解包

  • 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

遍历字典的 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

链式比较操作

  • Non-Pythonic
age = 18
if age > 18 and x < 60:
    print("yong man")
  • Pythonic
if 18 < age < 60:
    print("yong man")

行内判断 if/else 三目运算

  • Non-Pythonic
if gender == 'male':
    text = '男'
else:
    text = '女'
  • Pythonic
text = '男' if gender == 'male' else '女'

真值判断

  • Non-Pythonic
if attr == True:
    do_something()

if len(values) != 0: # 判断列表是否为空
    do_something()
  • Pythonic
if attr:
    do_something()

if values:
    do_something()

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 循环遍历完所有元素之后执行。

字符串格式化

  • 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")

列表切片

  • 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[:]

善用生成器

  • 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

生成器的好处就是无需一次性把所有元素加载到内存,只有迭代获取元素时才返回该元素

用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
from collections import Counter

x_list = ['Ozil', 'Ramsey', 'Ozil', 'Ramsey', 'Giroud']
x_dict = Counter(x_list)
print(x_dict)

bye