Pythonの入門者にいくつかのプログラミングの提案をあげます

5256 ワード

Pythonは非常に表現力のある言語です.膨大な標準ライブラリと多くの組み込みモジュールを提供し、迅速な作業を支援します.しかし、多くの人が提供する機能に迷って、標準ライブラリを十分に利用できず、単行スクリプトを過度に重視したり、Pythonの基本構造を誤解したりする可能性があります.本稿はPython初心者が陥る可能性のあるトラップの不完全なリストです.
Pythonバージョンがわかりません
これはStackOverflowで繰り返される問題です.多くの人があるバージョンで完璧に動作するコードを書くことができますが、自分のシステムには異なるバージョンのPythonがインストールされています.あなたが使用しているPythonバージョンを知っていることを確認してください.
下のコードでPythonバージョンを表示できます.

$ python --version
Python 2.7.9

バージョンマネージャを使用しない
pyenvは異なるPythonバージョンを管理する優れたツールですが、残念ながら*nixシステムでしか動作しません.Macシステムでは、brew install pyenvで簡単にインストールできます.Linuxにも自動インストールプログラムがあります.
1行のプログラムに夢中になる
多くの人が1行のプログラムがもたらす興奮感に熱中している.1つのロー・ソリューションが1つのロー・ソリューションよりも低効率であっても、彼らは吹聴します.
Pythonの1行のプログラムは本質的に複数の式を持つ複雑な導出を意味する.例:

l = [m for a, b in zip(this, that) if b.method(a) != b for m in b if not m.method(a, b) and reduce(lambda x, y: a + y.method(), (m, a, b))]

正直に言うと、私は上の例を作った.しかし、多くの人が似たようなコードを書いているのを見ました.このようなコードは1週間後には理解しにくくなります.条件に基づいて簡単にリストやコレクションに要素を追加するなど、少し複雑なことをしたい場合は、エラーを犯す可能性があります.
単行コードは成果ではありません.はい、柔軟に見えるかもしれませんが、成果ではありません.想像してみてください.これはあなたが部屋を掃除するときにすべてのものをクローゼットに詰めたようなものです.良いコードはきれいで、読みやすく、効率的であるべきです.
エラーによるコレクションの初期化
これはもっと微妙な問題で、手が回らないかもしれません.集合導出はリスト導出に似ている. 

>>> { n for n in range(10) if n % 2 == 0 }
{0, 8, 2, 4, 6}
>>> type({ n for n in range(10) if n % 2 == 0 })

以上が集合導出の一例である.コレクションはリストのようなもので、コンテナでもあります.異なる点は、1つのセットに重複する値がなく、無秩序であることです.集合を見ると,{}が空の集合を初期化できると勘違いすることが多い.しかし、実際にはそうではありません.空の辞書を初期化します. 

>>> {}
{}
>>> type({})

空のセットを初期化したい場合は、set()メソッドを簡単に呼び出すことができます. 

>>> set()
set()
>>> type(set())

空の集合はset()で表されますが、いくつかの要素を含む集合はカッコで要素を囲んで表されます. 

>>> s = set()
>>> s
set()
>>> s.add(1)
>>> s
{1}
>>> s.add(2)
>>> s
{1, 2}

これは直感とは逆です.set([1,2])に似たものを望んでいるからです.
誤解GIL
GIL(グローバルインタプリタロック)は、Pythonプログラムでは、任意の時点で1つのスレッドしか実行できないことを意味します.これは、スレッドを作成して並列に実行したい場合、そうではないことを意味します.Pythonインタプリタの実際の作業は,異なる実行スレッド間を迅速に切り替えることである.しかし、これは実際に起こったことに対する非常に簡単な解釈にすぎず、実際の状況は複雑だ.C拡張の本質を持つさまざまなライブラリを使用するなど、並列実行の例がたくさんあります.しかし、Pythonコードを実行すると、ほとんどの時間は並列に実行されません.言い換えれば、PythonのスレッドはJavaやC++のスレッドとは異なります.
多くの人がPythonのために弁解しようとしますが、これらは本当のスレッドだと言っています.これは確かに本当ですが、Pythonがスレッドを処理する方法があなたが望んでいる方法とは異なるという事実を変えることはできません.Ruby言語でも同じことがあります(Rubyにも解釈ロックがあります).
指定したソリューションはmultiprocessingモジュールを使用することです.Multiprocessingモジュールは、forkをよくカバーするProcessクラスを提供します.しかし、forkプロセスは1つのスレッドよりもずっとコストが高いので、異なるprocessの間で相互調整を行うために多くの仕事をする必要があるため、毎回性能の向上を見ることはできません.
しかし、この問題は各Pythonの実装バージョンには存在しない.例えば、Pythonの実装PyPy−stmは、GILから脱出しようとする(まだ安定していない).JVM(Jython)やCLR(IronPython)のような他のプラットフォームに構築されたPythonは、GILの問題もなく実現されています.
とにかく、Threadクラスを使うときは気をつけてください.あなたが得たのはあなたが望んでいるものではないかもしれません.
レガシークラスの使用
Python 2には「旧式」と「新式」の2種類がある.Python 3を使用する場合は、デフォルトで「新式」クラスを使用します.Python 2で「新式」クラスを使用するには、新しく作成した各クラスにobjectクラスを継承させ、intやlistなどの組み込みタイプを継承できないようにする必要があります.言い換えれば、あなたのベースクラス、クラスが他のクラスを継承しない場合は、常にobjectクラスを継承する必要があります. 

class MyNewObject(object):
# stuff here

これらの「新しい」クラスは、古いクラスの根本的な欠陥を解決しているので、深く理解する必要はありません.しかし、興味のある人がいれば、関連ドキュメントに関連情報を見つけることができます.
エラーによる反復
この言語の初心者にとって、下のコードは非常に一般的です.

for name_index in range(len(names)):
print(names[name_index])

上記の例では、リスト反復は実際にはより簡単であるため、len関数を呼び出す必要はありません.

for name in names:
print(name)

また、反復を簡略化するための他のツールもたくさんあります.たとえばzipを使用して、2つのリストを同時に巡回できます.

for cat, dog in zip(cats, dogs):
print(cat, dog)

リスト変数のインデックスと値を同時に考慮したい場合は、enumerateを使用します.

for index, cat in enumerate(cats):
print(cat, index)

itertoolsにも役に立つ関数がたくさんあります.ただし、itertools関数を使用すると、必ずしも正しい選択ではないことに注意してください.itertoolsの関数が解決しようとする問題に非常に便利な解決策を提供している場合、リストを平らにしたり、与えられたリストに基づいてコンテンツの配列を作成したりする場合は、それを使用しましょう.しかし、あなたがそれを望んでいるだけでコードの一部に適応しないでください.
itertoolsの乱用による問題は頻繁に発生しすぎて、StackOverflowの上で徳の高いPythonの貢献者はすでに彼らの資料の重要な構成部分に貢献してこれらの問題を解決しました.
可変のデフォルトパラメータの使用
次のコードを何度も見ました.

def foo(a, b, c=[]):
# append to c
# do some more stuff

可変のデフォルトパラメータは使用しないでください.次のコードで代用できます.

def foo(a, b, c=None):
if c is None:
c = []
# append to c
# do some more stuff

この問題が何であるかを説明するよりも、可変デフォルトパラメータの使用の影響を示します.

In[2]: def foo(a, b, c=[]):
... c.append(a)
... c.append(b)
... print(c)
...
In[3]: foo(1, 1)
[1, 1]
In[4]: foo(1, 1)
[1, 1, 1, 1]
In[5]: foo(1, 1)
[1, 1, 1, 1, 1, 1]

同じ変数cは、関数呼び出しのたびに繰り返し参照される.これは予想外の結果があるかもしれません.
まとめ
これらは相対的にPythonに触れたばかりの人が直面する可能性のある問題にすぎない.しかし、直面する可能性のある問題はそうではないことに注意してください.しかし、JavaやC++のようにPythonを使用し、よく知っている方法でPythonを使用しようとする欠点もあります.そこで、この文章の続きとして、Pythonのsuper関数など、いくつかのものを深く試してみましょう.クラスメソッド、静的メソッド、および__を参照してください.slots__など.