Python学習ノート(七):高級特性、関数式プログラミング、テンプレート(クイック入門編)


自分の学校の紹介を見てから、「ヘッドファイザーPython」と「Python基礎教程」の中にあるものを少なく話したと思います.そこで、廖雪峰のブログを借りてさらに補足します.http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000
補足ですので、ここでは前のノートに足りないものだけに言及して、繰り返し紹介しません.
高度な特性
リスト生成式
リスト生成式を使って、ファーストリストを素早く生成できます.リストから別のリストを導き出すことができますが、コードは非常に簡潔です.
[x * x for x in range(1, 11) if x % 2 == 0]
Result:[4, 16, 36, 64, 100]
生成器
generatorは非常に強力なツールであり、Pythonでは簡単にリスト生成式をgeneratorに変更することができ、関数によって複雑な論理を実現するgeneratorにもなります.
generatorの動作原理を理解するには、forサイクルの過程で次の要素を計算し、適切な条件でforサイクルを終了します.関数が変更されたgeneratorにとって、return文または関数体の最後の行に実行された文は、generatorの命令を終了し、forループは終了します.
リスト生成式変更ジェネレータ
一つのリスト生成式の[]を()に変更するだけで、一つのgenerator「L=[x x for x in range(10)」(嗳リスト生成式g=(x x for x in range(10)を作成します.
一つのgeneratorを作成した後、基本的にはnext()メソッドは永遠に呼び出さず、forループで繰り返します.
yieldキーワードの生成器
推計のアルゴリズムが複雑で、似たようなリスト生成式のforサイクルでは実現できない場合は、関数でも実行できます.
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b         #print b
        a, b = b, a + b
        n = n + 1
関数は順番に実行されます.return文または最後の行の関数文が返ってきます.そして、generatorの関数となり、next()を呼び出すたびに実行します.yield文が戻ってきたら、再度実行します.前回返したyield文から実行します.
関数プログラミング
高次関数
関数をパラメータとして導入し、このような関数を高次関数と呼び、関数式プログラミングとはこのような高度に抽象的なプログラミングの範式を指します.
  • 変数は、関数
    >>> f = abs
    >>> f(-10)
    
  • を指すことができる.
  • 関数名も変数
    >>> abs = 10
    >>> abs(-10)
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: 'int' object is not callable
    
  • です.
    注:abs関数は実際には–builtin–モジュールに定義されていますので、abs変数を変更する方向は他のモジュールでも有効になります.–builtin–abs=10を使用します.
    map/reduce
    map()関数は、2つのパラメータを受信し、1つは関数であり、1つはシーケンスであり、mapは、入力された関数をシーケンスの各要素に順次作用させ、結果を新しいlistとして返します.
    >>> map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    ['1', '2', '3', '4', '5', '6', '7', '8', '9']
    
    reduceは一つの関数を一つのシーケンス[x 1,x 2,x 3…]に作用させます.この関数は二つのパラメータを受信しなければなりません.結果を連続して次の要素と累積して計算します.その効果は:
    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
    
    filter
    Python内に構築されたfilter()関数は、シーケンスをフィルタリングするために使用されます.
    map()と同様に、filter()も一つの関数と一つのシーケンスを受信します.map()とは異なる場合、filter()は、入ってきた関数を順番に各要素に作用させ、戻り値がTrueかそれともFalseかによって、その要素を保留するかそれとも廃棄するかを決定します.
    def is_odd(n):
        return n % 2 == 1
    
    filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])  #   : [1, 5, 9, 15]
    
    戻り関数
    関数を返します.
    def lazy_sum(*args):
        def sum():
            ax = 0
            for n in args:
                ax = ax + n
            return ax
        return sum
    
    >>> f = lazy_sum(1, 3, 5, 7, 9)  #  lazy_sum() ,          ,      
    >>> f()  #    f ,          
    
    この例では関数Lazymusumに関数sumを定義し、内部関数sumは外部関数Lazymusumのパラメータと局所変数を参照してもいいです.lazymusumが関数sumに戻ると、相関パラメータと変数は戻りの関数に保存されます.このような「クローズド」と呼ばれるプログラム構造は大きな威力を持っています.
    もう一つ注意してください.lazymusum()を呼び出すたびに新しい関数が戻ります.同じパラメータが入っても
    包みを閉じる
    閉じたパケットを返すときに心がけるポイントは、戻り関数は循環変数を参照しないか、またはその後に変化する変数を参照しないことです.
    循環変数を参照するにはどうすればいいですか?方法はもう一つの関数を作成して、この関数のパラメータで循環変数の現在の値をバインドします.このサイクル変数がその後どのように変更されても、関数パラメータの値にバインドされています.
    匿名関数
    >>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
        lambda x: x * x     :
    def f(x):
        return x * x
    
    キーワードlamdaは匿名関数を表し、コロンの前のxは関数パラメータを表します.
    匿名関数には制限があります.つまり、returnを書かずに表式だけができます.戻り値はこの表式の結果です.
    匿名関数を使うと、関数に名前がないので、関数名の衝突を心配する必要はありません.また、匿名関数も関数オブジェクトです.匿名関数を変数に割り当てて、変数を使って関数を呼び出してもいいです.
    飾り物
    OOPの装飾モードは継承と組合せで実現する必要がありますが、PythonはOOPのdecoratorをサポートする以外に、直接に文法レベルからdecoratorをサポートします.Pythonのdecoratorは関数で実現できます.クラスでも実現できます.
    decoratorは関数の機能を強化できます.定義はちょっと複雑ですが、使いやすいです.
    完全なdecoratorの書き方は以下の通りです.
    import functools
    
    def log(func):
        @functools.wraps(func)  #      __name__      wrapper()   ,  ,                 
        def wrapper(*args, **kw):   #wrapper()             
            print 'call %s():' % func.__name__  #       __name__  ,         
            return func(*args, **kw)    #func __name__      'func'   'wrapper'
        return wrapper
    
    またはパラメータ付きのdecoratorに対して:
    import functools
    
    def log(text):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print '%s %s():' % (text, func.__name__)
                return func(*args, **kw)
            return wrapper
        return decorator
    
    定義:
    @log('execute') #   log('execute')(now)
    def now():
        print '2013-12-25'
    
    偏関数
    関数のパラメータ数が多すぎて、簡略化が必要な場合、functools.partialを使って新しい関数を作成できます.この新しい関数は元関数の部分パラメータを固定して、呼び出し時により簡単になります.
    >>> import functools
    >>> int2 = functools.partial(int, base=2)
    
    テンプレート
    テンプレートを使う
    テストを実行
    if __name__=='__main__':
        test()
    
    コマンドラインでモジュールファイルを実行するとき、Pythonインタプリタは特殊変数–name–を–main–とします.他のところにこのモジュールを導入すると、ifは失敗すると判断します.このifテストはコマンドラインを通してモジュールを実行させる時に、いくつかの追加コードを実行します.最も一般的なのはテストを実行します.
    スコープ
    一つのモジュールでは、多くの関数と変数を定義することができますが、ある関数と変数は他の人に使いたいです.ある関数と変数はモジュールの内部でのみ使用したいです.Pythonでは、_プレフィックスによって実現されます.
    正常な関数と変数名は公開されており、直接参照されることができます.例えば、abc、x 123、PIなどです.
    このような変数は特殊変数です.直接参照できますが、上のような特殊用途があります.–name–は特殊変数です.モジュールで定義されたドキュメントの注釈も特殊変数–doc–でアクセスできます.私たち自身の変数は一般的にこの変数名を使わないでください.
    のような関数や変数は非公開です.直接引用されるべきではありません.例えば-abc、–abcなどです.
    prvate関数と変数が直接引用されるべきではなく、直接引用されるべきではないという理由は、Pythonはprvate関数や変数へのアクセスを完全に制限する方法がないからです.
    _futureを使う
    Pythonは–future–モジュールを提供しています.次の新しいバージョンの特性を現在のバージョンに導入して、現在のバージョンでいくつかの新しいバージョンの特性をテストできます.