個人的には、言語に入門する際にはオンラインより書籍が適切と考えている。
そして最初の一冊はなるべく薄いものを選ぶべきと考えている。
読んだ後、あえて文章として書き出すと良さそう。行間なりツボを自分の言葉でおまとめ。
あそこにこう書いてあった..というように思い出せると良いかなと。
まずは制御構造。
if … elif … else
ブロックの開始はコロン。ブロックはインデントで表現。
else ifは繋げて書く。elif,elseはオプション。
1 2 3 4 5 6 7 8 9 |
x = 20 if x < 0: print("負の値") elif x == 0: print("ゼロ") elif x == 1: print("いち") else: print("その他") |
for
初期値、終了値、増分を書くCスタイルと違う。シーケンスに対してforeachをかけるスタイルのみ。
ループにかけたからといってシーケンスがコピーされることはなく変更することができる。
当然不安定なのでシーケンスをコピーしてループに使うべき、。
1 2 3 4 5 6 |
words = [1,2,3,4,5] for x in words: print(x) # for x in words[:] words.insert(0,x) |
シーケンスを最後まで読み終わった後に実行するブロックを定義できる。
forと同じインデント位置にelseを書く。
1 2 3 4 5 6 7 8 9 10 11 |
words = [1,2,3,4,5] for x in words: print(x) else: print("finish") 1 2 3 4 5 finish |
range
ループはシーケンスを処理するのみなので、シーケンスが無い場合は作る必要がある。
nからn-1ならrange(n)。初期値、終了値、ステップはrange(初期値,終了値,ステップ)。
range(n)はシーケンスを作るのではなく反復可能体を返す。つまり、range()の応答時には
シーケンスはメモリ確保されておらず評価時に初めてメモリ確保される。ref.C++ iterator。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
for x in range(10): print(x**2) 0 1 4 9 16 25 36 49 64 81 for x in (range(0,10,3)) print(x) 0 3 6 9 |
シーケンスを最初から最後までなめるのは以下。
1 2 3 4 5 6 7 |
ary = ["hoge1","hoge2","hoge3"] for x in range(len(ary)): print(ary[x]) hoge1 hoge2 hoge3 |
break,continue
forループ,whileループを抜ける構文。
breakでforループを抜けた場合、for,whileに対応するelse:ブロックは評価されない。
1 2 3 4 5 6 7 8 9 10 |
words = [1,2,3,4,5] for x in words: print(x) if x==3: break else: print("finish") 1 2 3 |
pass, …
pass,または…と書くと何もしない行を書くことができる。
コードに対称性が無くなったときにあえて書いておきたくなりそう。
これは悪くないかも..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
words = [1,2,3,4,5] for x in words: print(x) if x==3: ... # don't forget elif x==4: pass # don't forget else: print("finish") 1 2 3 4 5 finish |
関数
関数の書き方。大方の言語のようにドキュメンテーションのやり方がある。
何故か関数の中に書く。docstringという。不思議。
後で自動集計してくれる。他のフォーマットを知っておきたい。
形式言語処理っぽい書き方だと、defの実行により新しいシンボル表が作られる。
関数内のあらゆる代入は新しいシンボル表に書かれる。(ローカルスコープ)。
関数内ではこのシンボル表しか参照することができず、implicitにグローバル変数を
参照できない。ほぅほぅ。
ローカルスコープからは、global識別子によりシンボルを修飾することで初めてグローバルの
シンボル表にアクセスできる。
実引数がコピーされてローカルシンボル表に加えられるのではない。
関数の実引数の参照がローカルシンボル表に加えられる。
1 2 3 4 5 6 7 8 9 10 |
def fib(n): """nまでのフィボナッチ級数""" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib(100) 0 1 1 2 3 5 8 13 21 34 55 89 |
関数名は1つのシンボルとして使える。以下のように
1 2 3 |
f = fib f(100) 0 1 1 2 3 5 8 13 21 34 55 89 |
関数は”return 値”により値を返す。”return”またはreturnを書かない場合,Noneを返す。
関数のデフォルト値
大方の言語と同じ書き方でデフォルト値を書ける。
1 2 3 4 5 6 7 8 9 10 |
def fib(n=100): """nまでのフィボナッチ級数""" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib() 0 1 1 2 3 5 8 13 21 34 55 89 |
関数のデフォルト値は1回しか評価されない。最初に1度だけ評価された後使い回される。
以下は”[1],[2],[3]”とならない。
1 2 3 4 5 6 7 |
def hoge(x,L=[]): L.append(x) return L [1] [1, 2] [1, 2, 3] |
こう書いておくと期待通りになる。
1 2 3 4 5 |
def fuga(x,L=None): if L is None: L = [] L.append(x) return L |
キーワード引数
大方の言語と同じ書き方でキーワード引数を書ける。
引数の位置から解放される。キーワード引数でない引数は前に持ってくる。
1 2 3 4 5 6 7 8 9 10 11 |
def fib(n=100): """nまでのフィボナッチ級数""" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib(n=200) 0 1 1 2 3 5 8 13 21 34 55 89 144 |