fluent python-第5章一等関数-オブジェクト向け(第4章-テキストとバイトシーケンス付)

5639 ワード

第4章テキストとバイトシーケンス
人間はテキストを使用し、コンピュータはバイトシーケンスを使用します.
第5章一等関数
前言:
Pythonでは、関数は1等オブジェクトです.プログラミング言語理論家は「一等オブジェクト」を以下の条件を満たすプログラムエンティティと定義する:1、実行時に作成する2、変数やデータ構造に付与できる要素3、パラメータとして関数4に伝達できる、関数としての戻り結果
5.1関数を対象とする
map、filter、reduceの現代の代替品関数言語は通常map、filterとreduceの3つの高次関数(異なる名前を使用する場合があります).Python 3ではmapとfilterは内蔵関数ですが、リスト導出とジェネレータ式が導入されているため、それほど重要ではありません.リスト導出またはジェネレータ式はmapとfilterの2つの関数の機能を持ち、例のように読みやすくなります.
>>> list(map(fact, range(6))) ➊   # fact             n!
[1, 1, 2, 6, 24, 120]
>>> [fact(n) for n in range(6)] ➋
[1, 1, 2, 6, 24, 120]
>>> list(map(factorial, filter(lambda n: n % 2, range(6)))) ➌
[1, 6, 120]
>>> [factorial(n) for n in range(6) if n % 2] ➍
[1, 6, 120]
>>>

5.3匿名関数
Pythonの簡単な構文はlambda関数の定義体が純粋な式しか使用できないことを制限している.言い換えれば,lambda関数の定義体には値を付与することも,whileやtryなどのPython文を用いることもできず,パラメータリストでは匿名関数を使用するのに最適である.
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

パラメータとして高次関数に渡されるほか,Pythonでは匿名関数はあまり使われない.文法上の制限のため、平凡ではないlambda式は読みにくいか、書けないかのどちらかだ.
5.4呼び出し可能オブジェクト
呼び出し演算子(すなわち())は、ユーザ定義関数に加えて、他のオブジェクトにも適用できます.オブジェクトが呼び出されるかどうかを判断するには、組み込まれたcallable()関数を使用します.Pythonデータモデルドキュメントには、7つの呼び出し可能なオブジェクトがリストされています.
  • ユーザー定義関数:def文またはlambda式を使用して作成します.
  • 内蔵関数
  • ビルトインメソッド
  • メソッド
  • クラス
  • クラスの例
  • ジェネレータ関数

  • 5.5ユーザー定義の呼び出し可能タイプ
    Python関数が真のオブジェクトであるだけでなく、どのPythonオブジェクトも関数のように表現できます.このためには、インスタンスメソッド__call__を実装するだけでよい.
    import random
    class BingoCage:
        def __init__(self, items):
            self._items = list(items)
            random.shuffle(self._items)   #     
        def pick(self):
            try:  # list = [1,2,3]; list.pop()   3,   list,   [1,2]
                return self._items.pop()
            except ImportError:
                raise LookupError('pick from empty BigoCate')
        def __call__(self):
            return self.pick()  #   bingo.pick()        bingo()
    
    bingo = BingoCage(range(3))
    print( bingo.pick() )   #   :0 or 1 or 2
    print( bingo() )   #             ; ⚠️bingo     ,        (),       
    print( callable(bingo) )  # True
    

    5.6関数内省__doc__に加えて、関数オブジェクトには多くのプロパティがあります.dir関数を使用して、factorial(定義された関数)に次の属性があることを確認します.
    >>> dir(factorial)
    ['__annotations__', '__call__', '__class__', '__closure__', '__code__',
    '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
    '__format__', '__ge__', '__get__', '__getattribute__', '__globals__',
    '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__',
    '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__',
    '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
    '__subclasshook__']
    >>>
    

    通常のオブジェクトがなく、関数にある属性をリストします.
    >>> class C: pass # ➊
    >>> obj = C() # ➋
    >>> def func(): pass # ➌
    >>> sorted(set(dir(func)) - set(dir(obj))) # ➍
    ['__annotations__', '__call__', '__closure__', '__code__', '__defaults__',
    '__get__', '__globals__', '__kwdefaults__', '__name__', '__qualname__']
    >>>
    

    ➊空のユーザー定義クラスを作成します.➊インスタンスを作成します.➌空の関数を作成します.➊差分セットを計算し、ソートして、クラスのインスタンスがなく、関数が持つ属性リストを取得します.
    5.7位置決めパラメータからキーワードパラメータのみ*argsパラメータは1つのメタグループ**kwargsパラメータは1つの辞書に格納されます
    5.11この章のまとめ
    本章の目標はPython関数の一等性を検討することである.これは、関数を変数に割り当てたり、他の関数に渡したり、データ構造に保存したり、フレームワークやツールで使用するために関数のプロパティにアクセスしたりすることができることを意味します.高次関数は関数式プログラミングの重要な構成部分であり、現在ではmap、filter、reduce関数が以前のようによく使われていないとしても、しかし、リストの導出(およびジェネレータ式などの類似の構造)やsum、all、anyなどの内蔵の帰約関数もある.Pythonでよく用いられる高次関数には、内蔵関数sortedminmaxおよびfunctools. partialがある.
    Pythonには、lambda式で作成された単純な関数から__call__メソッドを実装するクラスインスタンスまで、7つの呼び出し可能なオブジェクトがあります.これらの呼び出し可能なオブジェクトは、組み込まれたcallable()関数によって検出できます.各呼び出し可能オブジェクトは、キーワードパラメータと注釈のみを含む、同じ豊富な構文宣言形式パラメータをサポートします.どちらもPython 3が導入した新しい特性です.
    Python関数とその注釈には豊富な属性があり、inspectモジュールの助けで読み取ることができます.例えば、Signature.bindメソッドは、Pythonが使用するルールと同様に、柔軟なルールを使用して実パラメータをパラメータにバインドします.
    最後に、本章ではoperatorモジュールのいくつかの関数とfunctools.partial関数を紹介し、これらの関数があれば、関数式プログラミングには機能の限られたlambda式はあまり必要ありません.
    雑談
    Pythonは関数言語ですか?
    プログラミング言語の「パターン」は終わりに近づき、古い時代の遺留物であり、うんざりしている.現代言語の設計者がモデルを顧みない以上、私たちの授業はなぜ奴隷のようにその言葉に従うのか.
    その論文では、Python、Ruby、Perlなどの言語について何を知っていますか.それらの設計者は辛抱強く林奈階層を正確に実現していない.設計者は自分の意思に従って他の場所から特性を参考にして、過去の概念を完全に無視したちゃんぽんを作成した.Krishnamurthi氏は、言語を分類しようとしないことを指摘した.逆に,それらを特性の集約と見なすのがより有用である.Pythonに一等関数を提供するために関数式プログラミングの扉を開けたが,これはGuidoの目的ではない.彼は「Origins of Python's Functional Features」という文章を書いた.http://python-history.blogspot.com/2009/04/origins-of-pythonsfunctional-features.html)では、map、filter、reduceの最初の目的はPythonにlambda式を追加することです.これらの特性はAmrit Premによって貢献され、1994年にリリースされたPython 1.0に追加されました(CPythonソースのMisc/HISTORYファイルを参照してください.https://hg.python.org/cpython/file/default/Misc/HISTORY) .