関数 topic
import
モジュールをインポートする。
import math print(type(math)) # <class 'module'> print(math) # <module 'math' from '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so'>
from <モジュール名> import <オブジェクト名>でオブジェクトをインポートできる。
from math import pi print(pi) # 3.141592653589793 # 他のオブジェクトを使用しようとするとエラーNameErrorになる。 # print(math.radians(180)) # NameError: name 'math' is not defined
組み込み関数
関数オブジェクト
def hello(): print("ハロー") h = hello # 関数を変数に代入 h() # 関数オプジェクトを実行
- 引数に関数オブジェクトを渡す
def do(func): func() def hello(): print("ハロー") def bye(): print("バイバイ") h2 = hello do(h2) # 変数(関数オブジェクト)で渡す # ハロー do(bye) # 関数のまま渡す # バイバイ
クロージャ(関数閉包)
- 関数の中に関数を定義する
戻り値に関数を返す
# クロージャの定義 def charge(price) : # 関数の実態 def calc(num) : return price * num return calc # クロージャ(関数オブジェクト)を2種類作る child = charge(400) # 子供料金400円 adult = charge(1000) # 大人料金1000円 # 料金を計算する price1 = child(3) # 子供3人 price2 = adult(2) # 大人2人 print(price1) # 1200 print(price2) # 2000
無名関数(ラムダ式)
lambda 引数, 引数,... : 実行するステートメント
func = lambda w, h : w * h num = func(3, 4) print(num) # 12
ラムダ式を直接実行
num = (lambda w, h: w * h)(3, 4) print(num) # 12
map(関数, イテラブル)
イテラブルの要素を関数に渡し、戻りをmapに格納する
def double(x) : return x * 2 nums = [4, 3, 7, 6, 2, 1] nums2 = map(double, nums) print(nums2) # <map object at 0x1071661d0> print(list(nums2)) # mapはlist()で変換できる # [8, 6, 14, 12, 4, 2]
- map()の関数にラムダ式を使う
nums = [4, 3, 7, 6, 2, 1] nums2 = map(lambda n : n * 2, nums) print(list(nums2)) # [8, 6, 14, 12, 4, 2]
- リストの内包表記で同一のロジックが書ける
nums = [4, 3, 7, 6, 2, 1] nums3 = [n * 2 for n in nums] print(nums3) # [8, 6, 14, 12, 4, 2]
filter(boolを返す関数 ,イテラブル)
- filter()を使って正の値だけを抜き出したリストを作る
nums = [4, -3, 9, 1, -2, -4, 5] nums2 = filter(lambda x : x>0, nums) # 関数をラムダ式で記述 print(nums2) # <filter object at 0x10f017ef0> print(list(nums2)) # [4, 9, 1, 5]
- リストの内包表記で同一のロジックが書ける
nums = [4, -3, 9, 1, -2, -4, 5] nums2 = [n for n in nums if n > 0] print(nums2) # [4, 9, 1, 5]
イテレータとジェネレータ
イテレータは要素を1つづつ取り出せるオブジェクト
(イテラブルなオブジェクトとは違い、呼び出し場所が自由)
ジェネレータ関数はイテレータ(イテレータのように要素を取り出せるオブジェクト)をつくる関数
イテラブルからイテレータをつくる : iter(イテラブル)
colors = ["red", "blue", "green"] colors_iter = iter(colors) print(colors_iter) # <list_iterator object at 0x10e301f98> print(next(colors_iter)) # イテレータの次の要素を取り出す # red print(next(colors_iter)) # blue print(next(colors_iter)) # green print(next(colors_iter)) # Traceback (most recent call last): # イテレータが空なのでエラーになる # File "/test_def_topic.py", line 61, in <module> # print(next(colors_iter)) # StopIteration
ジェネレータ関数でイテレータをつくる
def menu_generator() : yield "ワイン" # ジェネレータの戻りはyeild(イールド) yield "サラダ" yield "スープ" yield "ステーキ" yield "アイスクリーム" menu = menu_generator() # ジェネレータ関数でmenuジェネレータをつくる print(type(menu)) # <class 'generator'> print(next(menu)) # ワイン
ジェネレータオブジェクトをfor-inで回す
def menu_generator() : yield "ワイン" # ジェネレータの戻りはyeild(イールド) yield "サラダ" yield "スープ" yield "ステーキ" yield "アイスクリーム" menu = menu_generator() for n in menu: print(n) # ワイン # サラダ # スープ # ステーキ # アイスクリーム
ループのジェネレータ関数
def num_generator() : n = 0 while True : # ループにしとく num = n*n + 1 # 数列式 num = yield num n += 1 gen = num_generator() # ジェネレータを作る for i in range(0, 5) : print(next(gen)) # ジェネレータから次の値を取り出す # 1 # 2 # 5 # 10 # 17
ジェネレータ式
内包表記と似ている
odd_gen = (odd for odd in range(1, 6, 2)) # ()で囲む print(next(odd_gen)) # 1 print(next(odd_gen)) # 3
ジェネレータに値を送る : send(値)
def testgen() : n = 0 while True : received = yield n # send()の値が入る if received : n = received else : n = n + 1 # nがnext()で取り出される gen = testgen() # ジェネレータをつくる print(next(gen)) # 0 print(next(gen)) # 1 print(gen.send(10)) # ジェネレータに値を送る # 10 print(next(gen)) # 11
サブジェネレータ(サブイテレータ)
サブジェネレータ : yield from ジェネレータ
サブイテレータ : yield from イテラブル
def main_gen(n): # メインのジェネレータ yield "start" yield from range(n, 0, -1) # サブイテレータから値を作る yield from "abc" # サブイテレータから値を作る yield from [10, 20, 30] # サブイテレータから値を作る yield from sub_gen() # サブジェネレータから値を作る yield "end" # サブジェネレータ def sub_gen(): yield "X" yield "Y" yield "Z" m = main_gen(3) print(list(m)) # ['start', 3, 2, 1, 'a', 'b', 'c', 10, 20, 30, 'X', 'Y', 'Z', 'end']