def f(x):
return x ** 2
f(10)
100
def g(x):
return x * 2
# Integer -> Integer
g(10)
20
# Float -> Float
g(2.0)
4.0
# List -> List (期待通りではない)
g([1, 2, 3])
[1, 2, 3, 1, 2, 3]
for
ループ¶リストに対する操作は for
ループを使う (numpy
を使わないならば ... )
x = [1, 2, 3]
for i in x:
print(i * 2)
2 4 6
リストを返すようにするにはこうする
y = []
for i in x:
y.append(i * 2)
y
[2, 4, 6]
もっとよい方法
[i * 2 for i in x]
[2, 4, 6]
for
は色々な局面で現れるのでマスターしておく。ただし数値計算をする場合には頼りすぎないこと
自分で作った関数をファイルに保存しておく方法。IPythonから呼び出す場合は, IPython のカレントディレクトリをファイルがある場所に移動しておく。
# カレントディレクトリへのパスを表示
%pwd
'/Users/kenjisato/Dropbox/Lectures/2015/kobe-u/py/2015-05-20'
# カレントディレクトリのファイルをリストアップ
%ls
Untitled.ipynb __pycache__/ duck.py klass.py note.py
# ファイルの内容を表示
%cat note.py
# Generators def logistic(x): """Logistic map""" return 4 * x * (1 - x) def logistic_path(x, length): y = [x] for _ in range(length - 1): y.append(logistic(y[-1])) return y def logistic_gen(x, length): for _ in range(length): x1 = logistic(x) yield x x = x1
# ファイルを実行
%run note.py
logistic(0.2)
0.6400000000000001
logistic_path(0.2, 5)
[0.2, 0.6400000000000001, 0.9215999999999999, 0.28901376000000045, 0.8219392261226504]
for x in logistic_gen(0.2, 5):
print(x)
0.2 0.6400000000000001 0.9215999999999999 0.28901376000000045 0.8219392261226504
上で定義されている logistic_gen
はジェネレータ関数と呼ばれるもの. 関数定義の中で return
の代わりに yield
を使っている. ループの中でyield
を使うと, yield
文が実行されるたびに関数の実行が一時停止する. デザイン上の理由でたくさんのデータを返す関数を作るよりも必要なデータをひとつずつ出力するほうが望ましい場合に使う
def pm_gen(maxnum):
n = 0
while n < maxnum:
if n % 2 == 0:
yield 1
else:
yield -1
n += 1
list(pm_gen(10))
[1, -1, 1, -1, 1, -1, 1, -1, 1, -1]
%cat klass.py
import numpy as np class System: def __init__(self, dim): self.dim = dim def forward(self, x): pass class Logistic(System): def __init__(self, a): self.a = a super().__init__(dim=1) # System.__init__(dim=1) def forward(self, x): return self.a * x * (1 - x) class Tent(System): def __init__(self, a): self.a = a super().__init__(dim=1) def forward(self, x): return self.a * min(x, 1 - x) class Linear(System): def __init__(self, A): self.A = A super().__init__(dim=A.shape[0]) def forward(self, x): return np.dot(self.A, x) class NoUse: def forward(self, x): return 2 * x def run(system, x, steps): for i in range(steps): x1 = system.forward(x) yield x x = x1
run klass
A = np.array([[0.9, 0.0], [0.0, -0.5]])
ct = Linear(A)
x = np.array([2, 3])
for y in run(ct, x, 10):
print(y)
[2 3] [ 1.8 -1.5] [ 1.62 0.75] [ 1.458 -0.375] [ 1.3122 0.1875] [ 1.18098 -0.09375] [ 1.062882 0.046875] [ 0.9565938 -0.0234375] [ 0.86093442 0.01171875] [ 0.77484098 -0.00585938]
特定のクラスのインスタンスに対して動作する関数を定義したとする. 他のクラスのインスタンスが, その関数が正常に動作するのに必要な性質を備えていれば, クラスが違っても関数が正常に実行される
nu = NoUse()
list(run(nu, 1, 10))
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]