目次
Python
Pythonは numpyやPyTorchなどC++やCUDAで実装されたライブラリに 素早くアクセスできる優れたスクリプト言語.
配下ページ
- pillow (
from PIL import Image)
保存関係
pickle
with Path('hoge.pkl').open('wb') as f: pickle.dump(save_obj, f) with Path('hoge.pkl').open('rb') as f: save_obj = pickle.load(f)
npz
np.savez( Path('hoge.npz'), **{'a':array_a, 'b':array_b} ) with np.load(Path('hoge.npz'), allow_pickle=True) as load_dict: load_dict = {k:v for k,v in load_dict.items()}
Jupyter
JupyterLab
jupyter lab
で起動.デフォルトでは8888ポートで立てられる.
ポート指定して立てたい場合は
jupyter lab --port XXXXX
とすれば良い.
立てると自動でブラウザが起動されるはずだが、できないこともある. アクセスするには起動時に出てきたtokenでアクセスすれば良い.
http://localhost:8888/?token=xxxxxxxx
ssh経由でアクセスするなら
ssh -L ローカル側ポート:localhost:サーバー側ポート サーバー
gitでjupyter notebook管理
python環境下に nbstripout コマンドを入れておくと,
gitコミットにnotebookの出力が入らないようにできる.
以下を最初にやっておく
pip install --upgrade nbstripout nbstripout --install --attributes .gitattributes git add .gitattributes
あとは git commit 時に自動的にやられる.
jupyter
サブコマンド一覧
jupyter のサブコマンドをリストアップするには、 jupyter- と入力してタブ補完で探すのが良さそう。 jupyter のサブコマンドは jupyter-hoge という実行ファイルの形になっているので。
ノートのコマンドライン実行
- 実行結果削除
jupyter nbconvert --clear-output --inplace MYNOTEBOOK.ipynb
- ノートの実行(ノート自体の書き換え)
jupyter nbconvert --execute MYNOTEBOOK.ipynb --inplace --allow-errors
- ノートの実行(実行済みノートの新規作成)
jupyter nbconvert --to notebook --execute MYNOTEBOOK.ipynb \ --output OUTPUT.ipynb --ExecutePreprocessor.timeout=2678400 --allow-errors
scikit-image
scikit-imageには画像変換などに有用な関数などがある.
テスト用画像
skimage.data 配下に画像データ自体が入っているので以下のようにして
ndarray形式の画像を得ることができる.
from skimage.data import astronaut img = astronaut()
PIL.Image を使ってJupyter上で可視化
from PIL import Image Image.fromarray(img)
pandas
関数
DataFrame インスタンスを df と表すことにする.
| ヘッダのキーリスト | df.columns.values.tolist() |
現在の名前空間/import可能
globals(): インスタンス化されているものとimportされたパッケージ.(ビルトインオブジェクトのコンストラクタは含まれない)locals(): インスタンス化されているもの.
Pythonのビルトインオブジェクト
Pythonに最初から組み込まれていて既に使用されている変数名などが
builtinsを見ればわかる. listやdict,mapなど最初から使える関数がビルトイン.
names = __builtins__.__dict__.keys() print(names)
すべての組み込みオブジェクトはimport builtinsして
builtins.open()みたいな感じで正式名称で利用できる.
Pythonの標準ライブラリ
標準ライブラリディレクトリの中から __init__.py のあるディレクトリと __init__.py 以外の pythonファイルを列挙.
import distutils.sysconfig from pathlib import Path stdlibs = [ item.name.replace('.py','') for item in sorted( Path(distutils.sysconfig.get_python_lib(standard_lib=True)).glob('*') ) if ( item.is_dir() and (item/'__init__.py').exists() ) or ( item.name[-3:]=='.py' and item.name!='__init__.py' ) ] print(stdlibs)
import distutils.sysconfig from pathlib import Path stdlib_path = Path(distutils.sysconfig.get_python_lib(standard_lib=True)) stdlib_dynamic_load_path = stdlib_path / 'lib-dynload' std_mods = [ item.name.replace('.py','') for item in sorted( stdlib_path.glob('*.py') ) if item.name!='__init__.py' ] std_pkgs = [ item.name for item in sorted( stdlib_path.glob('*') ) if item.is_dir() and (item/'__init__.py').exists() ] std_dynl = [ item.name.split('.')[0] for item in sorted( stdlib_dynamic_load_path.glob('*.so') ) ] std_libs = list(sorted(std_mods + std_pkgs + std_dynl)) print(std_libs) print('debug console : ', len(std_mods), '(std_mods) +', len(std_pkgs), '(std_pkgs) +', len(std_dynl), '(std_dynl) =', len(std_libs), '(std_libs)' )
Pythonの読み込み可能なパッケージについて(サード/自作)
すでに名前空間に存在するパッケージを表示できる.
以下のように確認するとたとえばtestというパッケージはすでに標準ライブラリとして存在するので,
自分でtest.pyなどというファイルを作るのはあまりよろしくないということがわかる.
import pkgutil arr = sorted([p.name for p in pkgutil.iter_modules() if p.ispkg ]) for p in arr: print(p)
pkgutil.iter_modules() は sys.path以下と相対パスの
pythonファイル / soファイル / __init__.py のあるディレクトリ(パッケージ)
を列挙する.
標準ライブラリも含まれる.
デバッグ用途
何のメソッド・プロパティを持つか確認
あるオブジェクトが何のメソッド・プロパティを持っているか調べる.
プロパティとメソッド両方なら
[k for k in dir(obj) if not k.startswith('__')]
メソッド単体なら
obj.__dict__.keys()
確認
obj を確認したい場合.
nr_prop_meth = set(k for k in dir(obj) if not k.startswith('__')) sp_prop_meth = set(dir(obj)) - nr_prop_meth nr_meth = set(k for k in obj.__dict__.keys() if not k.startswith('__')) sp_meth = set(obj.__dict__.keys()) - nr_prop nr_prop = nr_prop_meth - nr_meth sp_prop = sp_prop_meth - sp_meth print('=== normal method ===') print(list(sorted(list(nr_meth)))) print('=== special method ===') print(list(sorted(list(sp_meth)))) print('=== normal property ===') print(list(sorted(list(nr_prop)))) print('=== special property ===') print(list(sorted(list(sp_prop))))
未整理メモ
分け方
- python基礎 型変換,基礎文法
- オブジェクト指向,各種プログラミングパラダイム
- パッケージ作成,import
標準ライブラリ(pipも3.4以降は標準)
切り捨て・切り上げ
ceil,floor
mathをimportするのは面倒
ceil = lambda x:-int((-x)//1) floor = lambda x:int(x//1)
三項演算子
python の三項演算子の書き方.
and-or スタイルは最後に評価されたものが返ってくる?
条件式 and 真戻り値 or 偽戻り値 だが、真戻り値は bool() で真になるものじゃないといけない
def func1(x): return 'fuga' if x=='hoge' else 'piyo' def func2(x): return x=='hoge' and 'fuga' or 'piyo' def f1(): print('eval 1') return 'bar' def f2(): print('eval 2') return 'baz' def func3(x): return x=='hoge' and f1() or f2() def main(): print(func1('hoge')) print(func1('foo')) print(func2('hoge')) print(func2('foo')) x = 'poon' z = ( x=='hoge' and 'fuga' or 'piyo' ) y = x=='hoge' and 'fuga' or 'piyo' print(z) print(y) print('------') print(func3('hoge')) print('------') print(func3('foo')) if __name__ == '__main__': main()
結果
fuga piyo fuga piyo piyo piyo ----- eval 1 bar ----- eval 2 baz
配列色々
内包表記について
- 単純に丸括弧で内包表記するとtuple内包表記ではなくGeneratorオブジェクトになる.
- tupleにしたい場合は
tuple(i for i in range(10))みたいに最初にtupleとつける. - dict についても内包表記で生成できる
listの初期化
- MxN二次元配列は
[[0]*N for _ in range(M)]
のように初期化する.こうせず
[[0]*N]*Mとするとidが同じになってしまう.>>> N,M = 3,4 >>> x = [[0]*N]*M >>> x[0][1] = 3 >>> x [[0, 3, 0], [0, 3, 0], [0, 3, 0], [0, 3, 0]]
- range より短い書き方として strを使うものがある
[[0]*N for _ in ' '*M]
listを固定個数ずつ取り出し
同一オブジェクトとなることを利用して以下のように順番に3つずつの組にするなどのテクニックがある.
ただし個数が割り切れない場合は最後のほうのは使われなくなる(zipの仕様による挙動).
>>> zip(*[iter(range(15))]*3) [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
より読みやすい書き方としては (何個ずつ切り分けるかがわかっているときは)
>>> l = [i for i in range(15)] >>> zip(l[::3],l[1::3],l[2::3]) [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
2次元配列の転置
以下はtupleのlistを作成してしまう.それで問題ない場合はこの書き方が一番短い.
LT = list(zip(*L))
listのlistをとして転置したものを作成したい場合は
LT = [[*l] for l in zip(*L)]
配列から同じ個数ずつ取り出し
ここまでは、端数が出たとき最後の配列が少なくなる状況だった。
たとえば 21=[5,5,5,5,1] みたいになる。これを 21=[5,4,4,4,4] としたい。
その場合、
# target : 配列 num_split = 3 nums = [ len(target)//num_split+int(i<len(target)%num_split) for i in range(num_split)] splits = [ (slice(l[0],l[0]+n),l.append(l.pop()+n))[0] for l in [[0]] for n in nums ] splitted = [target[sl] for sl in splits] num_split = 3 nums = [ len(target)//num_split+int(i<len(target)%num_split) for i in range(num_split)] splitted = [ (target[l[0]:l[0]+n], l.append(l.pop()+n))[0] for l in [[0]] for n in nums ]
generatorの展開
# * を使うのが良い。 # 複数の generator から展開してまとめるときは [*hoge, *fuga, *piyo] # 無数のgeneratorから展開してまとめるときは sum([[*g] for g in g_list],[])
内包表記の旅
while
MAX = 5 hoge = 0 while True: if fuga() and hoge>MAX: break else: continue
みたいにしたいときの内包表記
depth = [i for loop in [[0]] for i in loop if not \ (loop.clear() if len(l)<size*-~i or l[size*i:size*-~i]!=indent else loop.append(i+1) )][-1]
- 内包表記のケツの filter-if に常にlistのメソッド戻り値を入れてやる.
- listの
clear()やappend()は何も返さないので常にFalse - if not False であるから常に filter されずに残せる.
- 計算したときの i を保存しておいてやる.
- 保存された最後が0なら0で止まった == 一つもないよ
- 保存された最後がNならNで止まった == 0からN-1までは通った == N個あるよ
相互参照
Mutual recursion
定義前の関数を参照しないと定義できない再帰関数の利用.
even = lambda n: True if n==0 else odd( abs(n)-1) odd = lambda n: False if n==0 else even(abs(n)-1)
対話モードの表示とprint関数の違い
オブジェクトに設定されたどの特殊属性(magic variable)が表示されるか
| 対話モード | __repr__ |
| print関数 | __str__ |
printでの表示に対する色付け
普通のシェルと同じ様にエスケープシーケンスで 標準出力に着色することが可能.
モード変更とモード終了のエスケープを利用する.
| 操作 | 文字列 |
|---|---|
| 元に戻す | \033[0m |
| 黒色にする | \033[30m |
| 赤色にする | \033[31m |
| 緑色にする | \033[32m |
| 黄色にする | \033[33m |
| 青色にする | \033[34m |
| 紫色にする | \033[35m |
| 水色にする | \033[36m |
| 白色にする | \033[37m |
| 太くする | \038[1m |
| 下線を付ける | \033[4m |
| 反転? | \033[08m |
| 逆? | \033[07m |
オブジェクト指向について
プライベート変数は擬似的にしか作れない.self.__param とすると外からは
アクセスできないが,_classname__param としてアクセスできる.
自作スクリプトをPythonで作成
pipで自作コマンドをインストールする方法.
pipとかはリポジトリのルートディレクトリに置かれたsetup.pyを見て実行される.
setup.pyの中では,setuptoolsという非標準パッケージを利用しているが,
pipが入っているとまず入っているので大丈夫.
setuptoolsのsetup関数にわたす値で色々と設定する.
entry_pointsという引数に以下のようにわたしてやれば良い.
entry_points={
"console_scripts": [
"hoge = fuga.piyo:main"
]
}
この例ではfugaパッケージpiyoモジュールのmain関数がhogeというコマンドで呼び出されることになる.
setuptoolsは内部ではdistutilsという標準パッケージを利用している.
パッケージのimportなどについて
- importの躓きどころ実行するファイルとimportできるものとの関係性について
ファイルハッシュの計算
hashlibという標準ライブラリがある.
import hashlib with open('hoge.txt','rb') as f: bindata = f.read() SHA1 = hashlib.sha1(bindata).hexdigest() print('SHA1 :',SHA1) MD5 = hashlib.md5(bindata).hexdigest() print('MD5 :',MD5)
16進数表現への変換
bytesは組み込み型.標準ライブラリstructを使って変換する.
import struct float_value = 1.234 hex_value = bytes.hex(struct.pack("f",float_value)) print(type(hex_value)) # <class 'str'>
コメントブロック
text = r""" こうやって 文字列を 好き放題書ける """ print(text)
ファイルの入出力
テキストファイルを開く場合は
with open('filename.txt',MODE) as f:
# 何らかの処理
とする.
openしてcloseする方式でも良いが,
なるべくファイルの処理がプログラム中の一部に収まるようにすることが大切.
closeされている/されていない の状態管理を適切にするのは常人の脳では不可能.
mode
| 指定 | 存在しないファイル | 存在するファイル | 操作 |
|---|---|---|---|
r | エラー | 変更なし | 読み込み |
w | 新規作成 | 消去 | 書き込み |
x | 新規作成 | エラー | 書き込み |
a | 新規作成 | 追記 | 書き込み |
その他,
バイナリファイル用のb,
読み書き両用(途中の箇所に追加など)の+
操作
- read
- write
argparse
import argparse def parse_args(): parser = argparse.ArgumentParser(description='ここにプログラムの説明文') parser.add_argument('-v','--value_name', type=str, default='hogehoge', dest='value_name', help='変数の説明') parser.add_argument('-f','--flag_name', action='store_true', dest='flag_name', help='boolの変数') args = parser.parse_args()
無理やりインデントによる可読性向上
何もしないと指定のインデントにしなければいけない
a = 0 x = 1 y = 2
if に恒等真なものを与えるとインデントを強制的に下げられる.
これによりブロックを作りコードの行をグループ分けできる.
if の中身を文字列にするのがコメント替わりにもなって良い.
if 'hoge': a = 0 if 'fuga': x = 1 y = 2
if のコメント部分を print したい場合は次のように工夫する.
if [print('hoge')]: a = 0 if {print('hoge')}: b = 0 if (print('fuga'),): x = 1 y = 2
print() の返り値は None であるので list や set に変換すれば良い.
bool(None) は False だが bool([None]) は True である.
list, set は括弧の2文字だけでできるので楽.tupleの場合は括弧の二文字とカンマが必要となるため最適解ではない.
print() の前に 1 or を付けることで簡単に print() が評価されずに True となり,
簡単にprintする/しないを切り替えられる.
if 1 or [print('表示されない')]: a = 0 if 0 or [print('表示される')]: x = 1 y = 2
変数名として ignore_flag としておくことで
一括で簡単に表示非表示を切り替えられる.
ignore_flag = True if ignore_flag or [print('表示されない')]: a = 0 if ignore_flag or [print('表示されない')]: x = 1 y = 2
with で利用できるクラスを作成したら良い.
class MSG: def __init__(self,step): self.step=step def __enter__(self): print(self.step,'start...') def __exit__(self,*arg): print(self.step,'done.') with MSG('last step'): print('do something')
class MSG: def __init__(self,step,flag=True): self.step,self.flag=step,flag def __enter__(self): not self.flag or print(self.step,'start...') def __exit__(self,*arg): not self.flag or print(self.step,'done.')
デコレータ
def hoge(func): return None @hoge def fuga(): hoge
def timelimit(msec): def _deco(func): def wrapper(*args, **kwargs): return func(*args,**kwargs) return wrapper return _deco @timilimit(1000) def some_func(): return 'hoge'
