====== Python ======
===== 概要 =====
* スクリプト言語の一つ
* 関数や if 文などの {} をインデントで代用するため、可読性が高い
* 2.x と 3.x で完全な互換性はない
* Linux の主要ディストリビューションには、デフォルトでインストールされている
* スクリプト言語の中では、高速に処理できるらしい
* 科学計算などのライブラリが充実している
* 対話的にプログラムができる (命令文のテストなどちょっと試したい時に最適)
* その他、便利な特徴: [[http://webtech-walker.com/archive/2010/10/13191417.html | Python初心者によるPythonのいいところ、はまりどころのまとめ - Webtech Walker]]
===== インストール =====
* [[Python/anyenv を用いた Python のインストール方法]]
===== 構文 =====
==== ファイルの先頭 ====
* Python 2\\
#!/usr/bin/env python
# -*- coding: utf-8 -*-
* Python 3\\
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
* 1 行目は実行するプログラムを指定するシバン行
* ''/usr/bin/env ...'' の代わりに直接 Python のパスを指定しても良い
* env は引数のプログラミング言語のパスを自動で拾ってきてくれる
* 環境が違っても env があれば、対応できるプログラムになる
* 2行目に文字コードを指定する (日本語などが含まれる場合、指定しないとエラーになる)
==== 変数 ====
* 定義\\ variable_name = value
* Python では変数の型が動的に割り当てられるため、型定義は不要
==== 配列 (リスト) ====
* 定義\\ array_name = [value1, value2, ...]
* リストは角括弧で定義
* 呼び出し\\ print(array_name[index])
* 配列名の後に角括弧で、0 から始まる配列番号を入れると個別に値を取り出すことができる
* index が負数だと、後ろからの番号になる (-1: 末尾の配列番号、-2: 末尾から1つ前の配列番号、...)
* スライスによる呼び出し\\ print(array_name[start:end])
* 連続する要素をリストとして呼び出すこともできる
* start 及び end は片方、省略でき、start を省略すると「先頭から」、end を省略すると「末尾まで」を指定したことになる
* start と end の数字は、要素の間の番号だと考えると良い\\
要素名 : val1 val2 val3 val4 val5
開始/終了番号: 0 1 2 3 4 5
* 例: 1:3 と指定した場合は上記の場合だと、val2 から val3 が得られる
* 参考サイト: [[http://www.kabipan.com/computer/python/ | www.kabipan.com/computer/python/]]
* 値の追加\\ array_name.append(value)
* append を使って、末尾に挿入する
* 参考サイト: [[http://d.hatena.ne.jp/yumimue/20071205/1196839438 | リスト - 作成、取り出し、置換、追加、検索、削除、要素数 - ひきメモ]]
==== 連想配列 (ハッシュ、ディクショナリ) ====
* Python でハッシュ (キーと値のペアで情報を持つ配列) をディクショナリと呼ぶ
* 定義\\ dic_name = {key1:value1, key2:value2, ...}
* ''dic_name'' にディクショナリ名
* ''key1'', ''key2'' にキー名
* ''value1'', ''value2'' に値
* 波括弧で定義
* 呼び出し\\ dic_name[key]
* 角括弧で呼び出す
* キーをリストで取得する\\ dic_name.key()
* ''dic_name'' にディクショナリ名
* for 文を使って hoge というディクショナリの値を取得する場合\\
for i in hoge.keys():
print(hoge[i])
* 値をリストで取得する\\ dic_name.values()
* 参考サイト: [[http://www.pythonweb.jp/tutorial/dictionary/ | 辞書(ディクショナリ) - Python入門]]
==== 関数の定義 ====
def function_name(arg1, arg2, ...):
...
* def で始め、''function_name'' に関数名を入れる
* 引数は関数名の後の () に入れた変数名に、関数の呼び出しで入れた引数が代入される
==== 関数の呼び出し ====
function_name(arg1, arg2, ...)
* 関数名 ''function_name'' をそのまま入れるだけ
* 引数 ''arg1'', ''arg2'' が引数として、関数に与えられる
==== 無名関数 (ラムダ(lambda)式) ====
* 即席関数 (関数として定義するでもないが、別の関数の引数に関数が必要な場合に便利)
* 構文\\ lambda arg:return
* ''arg'' は引数を指定 (複数指定する場合は、「,」で区切る)
* ''return'' に返り値を指定
* 例: 2倍の値を返す関数\\ >>>myfunc = lambda x: x*2
>>> myfunc(3)
6
* 例: 奇数に対し、True を返す関数\\ myfunc = lambda n: n % 2 == 1
>>> myfunc(3)
True
>>> myfunc(2)
False
* 後述する組み込み関数で使える
* 参考サイト
* [[http://www.lifewithpython.com/2013/01/python-anonymous-function-lambda.html | Pythonの無名関数(lambda)の使い方 - Life with Python]]
* [[http://emoson.hateblo.jp/entry/2014/10/14/022053 | lambda式はすごく面白い - 元理系院生の新入社員がPythonとJavaで色々頑張るブログ]]
==== 組み込み関数 ====
* 参考サイト: [[http://python.civic-apps.com/map-reduce-filter/ | map, reduce, filterによるシーケンス操作 | Python Snippets]]
=== map ===
* リストの要素、全てに対し指定した関数を実行する (for 文で各要素に処理するのと同じ)
* 構文\\ array_result = map(function, array)
* ''function'' にリストに対して処理したい関数を指定する
* ''array'' に処理したいリストを指定する
* 例: リストを浮動小数に変換する\\ result = map(float, hoge)
* 返り値は 2.x と 3.x で異なるため、[[#map_filter_zip_関数 | Python 2.x と 3.x の違い の map,filter,zip 関数]]を参照されたし
=== filter ===
* 条件に合致する値を抽出する (perl の grep みたいな関数)
* 構文\\ filter(function, array)
* ''function'' に条件判断する関数を指定する
* ''array'' に処理したいリストを指定する
* 例: 奇数のみ抽出する\\ >>> hoge = [1,2,3,4,5]
>>> filter(lambda n: n % 2 == 1, hoge)
[1, 3, 5]
* 返り値は 2.x と 3.x で異なるため、[[#map_filter_zip_関数 | Python 2.x と 3.x の違い の map,filter,zip 関数]]を参照されたし
=== reduce ===
* リストを集約する関数 (リストの値を for 分を使って取り出し、最終的に返り値を出す関数)
* 合計値を求める関数が reduce で代用できる
* 構文\\ reduce(function, array)
* ''function'' に集約する関数を指定する
* ''array'' に処理したいリストを指定する
* 例: 合計を算出する\\ >>> hoge = [1,2,3,4,5]
>>> reduce(lambda x,y: x+y, hoge)
15
* 3.x では functools モジュールに取り込まれたので、import してから使う\\
from functools import reduce
* 参考サイト: [[http://qiita.com/mriho/items/0cadc16c9c01e652db5e | 【備忘録】Python3でのreduce - Qiita]]
===== よく使う関数 =====
* [[python/print | print]]: 画面上に文字を表示する
===== よく使うモジュール =====
* [[python/argparse | argparse]]: コマンドライン引数を解析するモジュール
* [[python/Biopython | Biopython]]: アメリカの国立生物工学情報センターのデータベースにアクセスできる API モジュール
* [[python/easygui]]: 簡単なダイアログを表示するモジュール (qt 版も含む)
* [[python/itertools | itertools]]: イテレータ作成モジュール (順列や組み合わせ、直積、階乗で使える)
* [[python/joblib]]: 並列処理モジュール (別途導入が必要)
* [[python/math]]: 数学モジュール
* [[python/matplotlib | Matplotlib]]: グラフを描画するモジュール
* [[python/Notify | Notify]]: 通知バルーンモジュール (Linux のデスクトップ環境で通知する際に使う)
* [[python/numpy | numpy]]: 数値計算モジュール
* [[python/openpyxl]]: xlsx を編集するモジュール
* [[python/operator-itemgetter]]: 多次元配列を特定のキーで抽出するモジュール (ソートに使う)
* [[python/os | os]]: オペレーティングシステムインターフェースを扱うモジュール (ファイルの移動など)
* [[python/pandas | pandas]]: データフレームを扱うモジュール
* [[python/parmed | parmed]]: Gromacs や AMBER の構造やトポロジーファイルを扱うモジュール
* [[python/re | re]]: 正規表現を扱うモジュール
* [[python/scipy]]: 科学技術計算モジュール
* [[python/sqlite3 | sqlite3]]: SQLite を扱うモジュール
* [[python/subprocess]]: サブプロセスを扱うモジュール (外部コマンドを使うなど)
* [[python/sys | sys]]: システムパラメータを扱うモジュール (標準入出力やシグナルなど)
* [[python/textwrap]]: 行の長さなどを自動調整するモジュール
* [[python/tqdm]]: 進捗表示モジュール (別途導入が必要)
===== 自作モジュール =====
* 自作モジュールの作成手順 (実行する python ファイルを ''main.py''、モジュールファイルを ''module.py'' とする)
- 関数やクラスを列挙したモジュールファイル (module.py) を作成
- モジュールファイルがあるディレクトリに ''%%__init__.py%%'' というファイル名の空ファイルを配置する (モジュールファイルがあることを示すファイル)
- モジュールパスの追加
* **main.py と同じディレクトリにモジュールがある場合**\\
./main.py
./module.py
* main.py に ''import module'' を追加する (import の後は .py を抜いたファイル名を指定)
* **main.py と同じディレクトリにモジュールを含んだディレクトリ (module_dir) がある場合**\\ ./main.py
./module_dir/module.py
* main.py に ''import module_dir.module'' を追加する (module_dir と module.py の間はスラッシュではなく、ピリオドで区切る)
* main.py に ''from module_dir import module'' を追加する (ディレクトリとモジュールファイルを分ける場合)
* **main.py とは別の階層にモジュールを含んだディレクトリがある場合**\\ ./main.py
/path/to/module_dir/module.py
* 環境変数に追記する場合
- 環境変数 ''PYTHONPATH'' にモジュールディレクトリを追加 (ここでは端末上での表記だが、.bashrc や .zshrc などに記述すると恒久的に利用可)\\ $ export PYTHONPATH=$PYTHONPATH:/path/to/module_dir/
- main.py に ''import module'' を追加する (環境変数に追加したディレクトリから階層になっている場合は ''from'' や ''.'' を使って階層を示す)
* スクリプト内部で環境変数を追加する場合
- main.py に以下を追記\\ import sys
sys.path.append("/path/to/module_dir")
- main.py に ''import module'' を追加する (環境変数に追加したディレクトリから階層になっている場合は ''from'' や ''.'' を使って階層を示す)
* 参考サイト:
* [[http://otiai10.hatenablog.com/entry/2013/08/13/215034 | Python3のimport・下位/上位階層のモジュールをインポートしたい【import】【Python3】 - DRYな備忘録]]
* [[http://www.lifewithpython.com/2014/01/python-add-directories-to-path-to-import-libraries-from.html | Python Tips:ライブラリ読み込み対象ディレクトリを追加したい - Life with Python]]
* [[http://samurait.hatenablog.com/entry/__init__.py%E3%81%AE%E5%BD%B9%E5%89%B2 | __init__.pyの役割 - Python, web, Algorithm 技術的なメモ]]
* [[http://qiita.com/Accent/items/efb57d66309f6c0ee63d | Pythonで自作モジュールを手軽に使う - Qiita]]
===== Python 3.4 以降のモジュールのリロード =====
* 自作モジュール (''sample'') のリロード
- リロード用モジュールの読み込み\\ import importlib
- 通常のモジュール読み込み\\ import sample
- モジュールのリロード\\ importlib.reload(sample)
* ''from'' 付きのモジュールのリロード
- リロード用モジュールの読み込み\\ import importlib
- 通常のモジュール読み込み\\ from sample import SampleClass
- モジュールのリロード\\ import sample
importlib.reload(sample)
from sample import SampleClass
* 参考サイト: [[http://nihaoshijie.hatenadiary.jp/entry/2017/08/28/200626 | Python で class のみ reload - いっきに Python に詳しくなるサイト]]
* Python 2.x では ''reload()''、Python 3.3 までは ''imp.reload()'' を使うらしい…。
===== Python 2.x と 3.x の違い =====
* 2.x 以下のバージョンでは、完全な互換性があったようだが、3.x で一部機能について互換性がなくなった
* その違いをメモしてみた
==== Print ====
* [[http://mumeiyamibito.0am.jp/doku.php/python/print#python_2x_と_python3x_の違い | print() 関数]] のページを参照
==== map / filter / zip 関数 ====
* 2.x はリストで返す\\ >>> array = [1,2,3,4,5]
>>> print array
[1, 2, 3, 4, 5]
>>> print map(float, array) # 値をすべて浮動小数に変換して出力する
[1.0, 2.0, 3.0, 4.0, 5.0]
* 3.x はイテレータ (オブジェクト) で返す\\ >>> array = [1,2,3,4,5]
>>> print(array)
[1, 2, 3, 4, 5]
>>> print(map(float, array)) # 値をすべて浮動小数に変換して出力する
* 2.x のようにリストで返すには list 関数を用いる\\ >>> array = [1,2,3,4,5]
>>> print(list(map(float, array)))
[1.0, 2.0, 3.0, 4.0, 5.0]
* 2.x ではリストを処理する際に一度にのメモリを確保していたが、3.x (イテレータ) では、効率的にメモリを使うことができるらしい (巨大なリストを扱う際の負荷が少なくなる?)
* 参考サイト: [[http://qiita.com/croissant1028/items/94c4b7fd360cfcdef0e4 | Python 2 と 3 での高階関数の使い方の比較 - Qiita]]
===== Tips =====
==== 端末出力文字列に色を付ける ====
* エスケープシーケンスを使う
* 色を変える文字の前にエスケープシーケンスを挿入する
* ''\033'' (エスケープシーケンス) + ''['' + ''制御コード'' + ''m''
^ 分類 ^ 制御コード ^ 意味 ^
| 修飾 |0|リセット|
|:::|4|太字|
|:::|5|点滅(使用環境により使えない場合あり)|
|:::|7|反転|
| 文字色 |30|黒 (文字色)|
|:::|31|赤|
|:::|32|緑|
|:::|33|黄土色|
|:::|34|青|
|:::|35|赤紫 (マゼンタ)|
|:::|36|水色 (シアン)|
|:::|37|灰色 (暗めの白)|
|:::|90|暗めの灰色 (明るい黒)|
|:::|31|明るい赤|
|:::|32|明るい緑 (黄緑)|
|:::|33|黄色|
|:::|34|明るい青|
|:::|35|明るい赤紫 (マゼンタ)|
|:::|36|明るい水色 (シアン)|
|:::|37|白|
| 背景色 |40|黒|
|:::|41|赤|
|:::|42|緑|
|:::|43|黄土色|
|:::|44|青|
|:::|45|赤紫 (マゼンタ)|
|:::|46|水色 (シアン)|
|:::|47|白|
* 文字色や修飾を変更した場合、''\033[0m'' (リセット) を最後にしないと、次の出力でも同じ文字色 (修飾) で出力される。(リセットは一度で十分)
* 複数のコードを使いたい場合 (背景色と下線を使うなど)
* 1つのエスケープシーケンス内に複数のコードを '';'' で区切って記述する (例: ''\033[31;1;4;44m'')
* エスケープシーケンスを複数記述する (''\033[31m\033[1m\033[4m\033[44m'')
* ''termcolor'' モジュールの ''colored()'' 関数を用いる方法もある。
* やっていることは、与えられた文字列に対し、エスケープシーケンスを付加しているだけである。
* [[https://qiita.com/pytry3g/items/f23e3676a1c939f2d69e | とりあえずpythonでtermcolorを使ってみた - Qiita]]
* 参考サイト
* [[http://atomic.jpn.ph/prog/io/ansiesc.html | プログラム用例 - 入出力 - カラー文字]]
* [[http://qiita.com/hidai@github/items/1704bf2926ab8b157a4f | ターミナルで使える色一覧(8色ANSIエスケープシーケンス) - Qiita]]
==== 文字列を 1 文字ずつ区切る ====
* 文字列をリストに変換する。\\
text = "abcdefg"
list(text)
# -> ['a', 'b', 'c', 'd', 'e', 'f', 'g']
* 参考サイト: [[http://nfnoface.hatenablog.com/entry/2016/10/05/131600 | Pythonで文字列を1文字ずつ分割する - Webプログラムの技術メモ他]]
==== 定義済みのユーザ関数名の一覧を表示する ====
* 関数が定義済みかどうかを調べる時に使う (モジュールなどの外部のプログラムを使う時にどうぞ)。\\
import types
print([f.__name__ for f in globals().values() if type(f) == types.FunctionType])
* 参考サイト: [[https://stackoverflow.com/questions/6315496/display-a-list-of-user-defined-functions-in-the-python-idle-session | Display a list of user defined functions in the Python IDLE session - Stack Overflow]]
{{tag>プログラミング}}