文系データサイエンティスト怒天龍爆男のブログ

Pythonの高度な関数(Effective Python, エキスパートPythonプログラミング要約)

最近上司に「Python詳しくなってよ〜」と言われたので、Pythonの本を2冊読んでみました!
 

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

エキスパートPythonプログラミング改訂2版

エキスパートPythonプログラミング改訂2版

2冊とも内容は結構似ていたのですが後者の方が難しかった印象です。

ちなみに上記の「Effective Python」は、オライリーの「Effective Software Development」シリーズのPython版みたいです。

文系の私には2冊とも難しくて正直クラスとかメタクラスとかの内容はさっぱりわからなかったので、せめてもの抵抗として関数部分についてのみ備忘録として整理したいと思います😁

 

リストを返さずにジェネレーターを返す

ジェネレーターとはyield式を使う関数のことです。
例えば、以下のようにある値numまでの数値を二乗して表示するコードがあるとします。

コード:

def get_list_for_loop(num):
   
   list_for_loop = []

   for i in range(num):
   
      list_for_loop.append([round(i**0.5, 2), i**2])

   return list_for_loop

for i in get_list_for_loop(500):
   print(i)
                        

結果:

>>> 
[0.0, 0]
[1.0, 1]
[1.41, 4]
[1.73, 9]
.
.

このget_list_for_loopのようにリストを返す関数は、以下のようにジェネレーターで書き換えられます。

def gen_for_loop(num):
   
   for i in range(num):
   
      yield [round(i**0.5, 2), i**2]
   
for i in get_list_for_loop(500):
   print(i)

結果:

>>> 
[0.0, 0]
[1.0, 1]
[1.41, 4]
[1.73, 9]
.
.

ジェネレーターを使うことのメリットとして、以下のものがあるようです。

  • リストを操作するコード部分が減り、可読性が上がる
  • リストを返す関数にすると、一度にリストを完成させてしまう為、リストが大きい時にメモリを圧迫してしまう。ジェネレーターは逐次的に計算する為、上記の問題を避けられる。

関数をみた時にreturnじゃなくてyieldになってるとかっこいいので僕も暇な時使ってみたいと思います。😁

デコレーターを使って関数をラップする

デコレーターを使うと簡単に関数のラップ(機能追加)ができます。

def deco(func):
    def wrapper(*args, **kwargs):
        print("引数表示", *args, **kwargs)
        func(*args, **kwargs)
    return wrapper

@deco
def test(person):
    print('Hello {}'.format(person))

test("bakuo")

結果:

>>> 
引数表示 bakuo
Hello bakuo


この例のように関数の前後に何らかの処理を挟むことができます。
関数アノテーションなどと組み合わせると型チェックなどもできるようなので、「Pythonに型チェックないのキモいから自分で実装しちゃった😅」とか言えそうでいいですよね〜(僕はpythonとRしかやったことないのでその感覚がわからないですが。)


以上、簡単にはなってしまいましたがPythonの高度な(?)関数の紹介でした!