シコウノキロク

アラサー男が自由を手に入れるまでの思考と試行の記録。Python・お金・考察・学んだことが中心

入門Python3のメモ 4章|コード構造

Pythonの入門書として各所でオススメされている入門Python3。

shikouno.hatenablog.com

前半7章までで基本をおさらいし、後半8章からは他分野で活用できそうなちょっとした応用編がオールインワン。みんなのPython 第4版の次に読むとちょうどいいレベル感。

購入後にかいつまんでパラパラ読みはしていたのですが、まとまった時間が取れそうだったので一気通読しようかと思い立ちました。

その際、初めて知る箇所や曖昧でいつも検索する箇所を後で見返せるようにメモしておこうかと。

そのため、このメモは僕の知識的偏りから生み出されたものであることを最初にお断りしておきます。気になった方は書籍を購入してください。

入門 Python 3

ちなみに、1章は導入なのでメモがありませんが、1.2 Pythonと多言語の比較は面白いので必見!著者の冗談も随所に入っていて、面白くていい本です。

英語版はPDFが無料で公開されています。よろしければ!

Introducing Python

()を使った内包表記

  • 4.6.4 ジェネレータ内包表記

リスト、辞書、集合は内包表記を用いることでそれぞれのシーケンスを得ることができますが、タプルは内包表記でシーケンスを得ることができません。

()を使った内包表記はジェネレータが得られます。

>>> gen = ( x for x in range(1,5))
>>> gen
<generator object <genexpr> at 0x10cedaca8>

デフォルト引数値はイミュータブルなデータ型

  • 4.7.3 デフォルト引数値の指定

デフォルト引数値にミュータブル(変更可能)なデータ型を用いると、関数を呼び出すたびにデフォルト引数値が異なってしまいます。

デフォルト引数値は関数を呼び出した時ではなく、定義した時に設定されるためだからです。

そのため、変数を関数内で定義するかイミュータブル(変更不可能)なデータ型を用いる必要があります。

>>> def mutable(arg=[]):
...     arg += "a"
...     return arg
...
>>> mutable()
['a']
>>> mutable()
['a', 'a']

>>> def imutable1():
...     arg = []
...     arg += "a"
...     return arg
...
>>> imutable1()
['a']
>>> imutable1()
['a']

>>> def imutable2(arg=None):
...     if arg==None:
...         arg = []
...     arg += "a"
...     return arg
...
>>> imutable2()
['a']
>>> imutable2()
['a']

help()関数とdocstring

  • 4.7.6 docstring

help()関数は、引数に取った関数の説明を表示。docstringの内容を参照しています。

>>> def doc():
...     """
...     docstringと
...     help()関数の
...     使い方テスト
...     """
...     pass
...
>>> help(doc)

Help on function doc in module __main__:

doc()
    docstringと
    help()関数の
    使い方テスト

無名関数:ラムダ関数

  • 4.7.10 無名関数:ラムダ関数

短い処理の関数は、無名関数:ラムダ関数を用いると一行でかけるため行数を少なくすることもできますし、別の関数の引数に用いることもできます。

lambda 【引数】 : 【返り値】

>>> numbers = [ x for x in range(1, 5)]
>>> def edit(args, func):
...     for arg in args:
...         print(func(arg))
>>> edit(numbers, lambda x :str(x+x) + "!")
2!
4!
6!
8!

ジェネレータ:yield

  • 4.8 ジェネレータ

ジェネレータ関数を書く場合、returnではなくyieldで記述します。yieldは関数を呼び出すたびに、以前の値を参照してから処理して返り値を戻す。

また、returnは関数が終了してしまうため関数のループ処理内には記述しませんが、yieldでは関数のループ処理内に記述します。

>>> def counter():
...     count = 1
...     while count < 5:
...         yield count
...         count += 1

>>> for x in counter():
...     print(x)
...
1
2
3
4
5

デコレータ:@method

  • 4.9 デコレータ

関数を入力して別の処理を付加した関数を返す関数のことをデコレータと呼ぶ。言葉だけだと難しいぞ。

新しい関数の処理 = 元々ある関数の処理 + デコレータ関数の処理

機能を付与したい関数をデコレータ関数の内側にネストし、デコレートしたい関数の前に@デコレータ関数で呼び出す。うーん、言葉で説明しようとすると混乱するのでコード見た方がいいですね。

>>> def deco(func):
...     def print_name(*arg, **kwargs):
...         print('func_name:', func.__name__)
...         return func(*arg, **kwargs)
...     return print_name
...
>>> @deco
... def hoge():
...     return "do hoge!"
...
>>> hoge
<function deco.<locals>.print_name at 0x10d1430d0>
>>> hoge()
funcname: hoge
'do hoge!'

ローカルorグローバル名前空間

globals()はグローバル名前空間の内容を示す辞書を返し、locals()はローカル名前空間の内容を示す辞書を返す。

>>> arg = "global arg"
>>> def check_space():
...     arg = "local arg"
...     print("global:", globals())
...     print("local:", locals())
...
>>> check_space()
global: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'arg': 'global arg', 'check_space': <function check_space at 0x104613ea0>}
local: {'arg': 'local arg'}

さいごに

無名関数:ラムダ関数やデコレータは活用できる範囲が広そうなのでしっかり抑えておきたいですね。

最後までお読みいただきありがとうございました。それじゃ!

入門 Python 3

入門 Python 3