どのようにもっと優雅にpythonコードを書くか?


前言
Pythonという言語の最大の利点の一つは文法が簡潔で、良いコードは疑似コードのように、清潔で、清潔で、一目瞭然です。しかし、時々コードを書きます。特にPython初心者は他の言語の思惟習慣によって書きます。そのような書き方は運行速度が遅いだけではなく、コードを読むのも大変です。
「コンピュータプログラムの構造と解釈」の著者ハル・バールソンは、「Prograams must be written for people to read,and only incidentally for machines to execute.」
Pythonic(優雅で、正真正銘で、きれいな)コードを書くには、大牛コードをよく観察する必要があります。Githubには非常に優秀なソースコードがたくさんあります。例えば、requests、flash、tonadoなど、よくあるPythonic書き方を挙げます。
1、変数交換
ほとんどのプログラミング言語で2つの変数の値を交換する場合、一時変数を導入しなければなりません。

>>> a = 1
>>> b = 2
>>> tmp = a
>>> a = b
>>> b = tmp
pythonic

>>> a, b = b, a
2、サイクルサイクル区間要素

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)
xrangeは生成器オブジェクトを返します。生成器はリストよりメモリを節約します。ただし、xrangeはpython 2の書き方です。python 3はrange方法しかありません。特徴はxrangeと同じです。
3、索引のある位置の集合を巡回します。
集合を巡回するとき、集合のインデックス位置に使用する必要がある場合は、集合反復に直接的にインデックス情報がなく、一般的な方法で使用されます。

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)
4、文字列接続
文字列接続の場合、普通の方式は+で操作できます。

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はより効率的な文字列接続方式であり、+を使って操作するたびにメモリ内に新しい文字列オブジェクトを生成し、8回の遍歴を経て8文字列が生成され、無駄なメモリロスをもたらします。ジョイン法ではプロセス全体が文字列オブジェクトを生成するだけです。
5、ファイルを開く/閉じる
ファイル操作を実行する時、最後に忘れてはいけない操作はファイルを閉じることです。間違ってもcloseします。一般的な方法は、finnallyブロックに表示されるcloseメソッドを呼び出すことである。

f = open('data.txt')
try:
data = f.read()
finally:
f.close()
pythonic

with open('data.txt') as f:
data = f.read()
with文を使うと、ファイル操作が完了したら自動的にファイルオブジェクトを閉じます。
6、リスト導出式
一行のコードで簡単に問題を解決できる時は、二行を使ってはいけません。

result = []
for i in range(10):
s = i*2
result.append(s)
pythonic

[i*2 for i in xrange(10)]
これに似ているのは、ジェネレータ式、辞書式、ともにpythonicの書き方です。
7、善用装飾器
装飾器は業務ロジックと関係のないコードを抜き出してコードを清潔にしてくれます。また、装飾器は複数のところで再利用されます。例えば、爬虫類ホームページの関数は、このURLが過去に這われていたら、そのままキャッシュから取得します。そうでなければ、登ってきたらキャッシュに入れて、後から重複して登らないようにします。

def web_lookup(url, saved={}):
if url in saved:
return saved[url]
page = urllib.urlopen(url).read()
saved[url] = page
return page
pythonic

import urllib #py2
#import urllib.request as urllib # py3
def cache(func):
saved = {}
def wrapper(url):
if url in saved:
return saved[url]
else:
page = func(url)
saved[url] = page
return page
return wrapper
@cache
def web_lookup(url):
return urllib.urlopen(url).read()
装飾器でコードの表面を書くとコードの量がより多く感じられますが、キャッシュ関連のロジックを抜き出して、より多くの関数に呼び出すことができます。これで全体のコード量が少なくなります。業務方法が簡潔に見えます。
8、合理的な使用リスト
リストオブジェクト(list)は、更新操作よりもクエリー効率が高いデータ構造で、要素を削除したり、要素を挿入したりすると、実行効率が非常に低くなります。

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()
names.appendleft('mark')
dequeは双方向キューのデータ構造です。要素の削除と要素の挿入はとても早いです。
9、シーケンス解凍

p = 'vttalk', 'female', 30, '[email protected]'
name = p[0]
gender = p[1]
age = p[2]
email = p[3]
pythonic

name, gender, age, email = p
10、辞書を巡るkeyとvalue
方法は速度がそんなに速くないです。反復するたびに、key対応のvalueを検索し直します。
方法二辞書が非常に大きい場合、メモリの消耗が倍以上になります。

#    
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)
iteritemsは、ディズエミリオブジェクトに戻り、より多くのメモリを節約することができますが、python 3にはこの方法がありません。items方法だけがあります。
もちろん多くのpythonicの書き方がありますが、ここではいちいち列挙しません。
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。