Python学習の関数式プログラミング


Python学習ディレクトリ1.MacでPython 3 2を使用する.Python学習のデータ型3.Python学習の関数4.Python学習の高度な特性5.Python学習の関数式プログラミング6.Python学習のモジュール7.Python学習のオブジェクト向けプログラミング8.Python学習の対象向け高度プログラミング9.Python学習のエラーデバッグとテスト10.Python学習のIOプログラミング11.Python学習のプロセスとスレッド12.Python学習の正則13.Python学習の常用モジュール14.Python学習のネットワークプログラミング
練習コード
関数式プログラミングは抽象度の高いプログラミングモデルであり、純粋な関数式プログラミング言語で書かれた関数には変数がないため、任意の関数は、入力が確定すれば、出力が確定し、このような純粋な関数は副作用がないと呼ばれています.変数を使用できるプログラム設計言語は,関数内部の変数状態が不確定であるため,同じ入力で異なる出力が得られる可能性があるため,この関数には副作用がある.関数式プログラミングの特徴の一つは、関数自体をパラメータとして別の関数に転送することを許可し、また1つの関数を返すことを許可することです.
Pythonは関数式プログラミングを一部サポートしています.Pythonは変数の使用を許可するため、Pythonは純粋な関数式プログラミング言語ではありません.
関数はPython内蔵でサポートされているパッケージで、大きなコードを関数に分解し、1層1層の関数呼び出しで複雑なタスクを簡単なタスクに分解することができ、この分解はプロセス向けのプログラム設計と呼ぶことができる.関数はプロセス向けのプログラム設計の基本単位である.
関数式プログラミング(式の文字が1つ増えたことに注意してください)--Functional Programmingは、プロセス向けのプログラム設計にもまとめることができますが、数学計算に近い考えです.
まずコンピュータ(Computer)とコンピューティング(Compute)の概念を理解しなければならない.コンピュータの階層では,CPUは加減乗除命令コードや各種条件判断やジャンプ命令を実行するので,アセンブリ言語はコンピュータに最も近い言語である.計算とは数学的な意味での計算を指し、抽象的な計算ほどコンピュータのハードウェアから遠い.プログラミング言語に対応するのは、低級な言語ほど、コンピュータに近づくほど、抽象度が低く、実行効率が高く、例えばC言語である.高度な言語ほど,計算に近いほど抽象度が高く,Lisp言語のような実行効率が低い.
高次関数
pythonでは関数名が関数を指す変数であり,関数のパラメータも関数である場合,この関数を高次関数と呼ぶ.
def add(x, y, f):
    return f(x) + f(y)
add(1, -6, abs)

map/reduce
map()関数は2つのパラメータを受信し、1つは関数であり、1つはIterableであり、mapは入力した関数をシーケンスの各要素に順次作用させ、結果を新しいIteratorとして返す.
def f(x):
    return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(r))

>>> [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduceは1つの関数を1つのシーケンス[x 1,x 2,x 3,...]に作用し、この関数は2つのパラメータを受信しなければならない.reduceは結果をシーケンスの次の要素と累積計算し続け、効果は以下の通りである.
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

mapとreduceを組み合わせてstr 2 intの関数を整理できます.
from functools import reduce

DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def char2num(s):
    return DIGITS[s]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

filter
Pythonに組み込まれたfilter()関数は、シーケンスをフィルタするために使用されます.map()と同様に、filter()も関数とシーケンスを受信する.map()とは異なり、filter()は、入力された関数を各要素に順次作用させ、戻り値がTrueであるかFalseであるかに基づいて、要素を保持または廃棄するかを決定する.
たとえば、listで偶数を削除し、奇数だけを残します.
def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
#   : [1, 5, 9, 15]

sorted
リストのソート:
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]

さらに、sorted()関数も高次関数であり、key関数を受信してカスタムソートを実現することもできます.たとえば、絶対値サイズでソートします.
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

文字列のソート:
>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

大文字と小文字を無視:
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']

逆ソートを行うにはkey関数を変更する必要はなく、3番目のパラメータreverse=Trueに入力できます.
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']

戻り関数
定義#テイギ#
高次関数はパラメータとして関数を受け入れるほか,結果値として関数を返すこともできる.
可変パラメータの和を実現する.通常、和を求める関数は次のように定義されます.
def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return ax

しかし、すぐに和を求める必要がなく、後のコードで必要に応じて再計算したらどうなりますか?和を求める結果ではなく、和を求める関数を返すことができます.
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
lazy_sum()を呼び出すと、加算結果ではなく、加算関数が返されます.
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
.sum at 0x101c6ed90>

関数fを呼び出すと、本当に合計の結果が計算されます.
>>> f()
25

クローズドパッケージ
上述した例では、関数lazy_sumにおいてさらに関数sumを定義し、内部関数sumは、外部関数lazy_sumのパラメータおよび局所変数を参照することができ、lazy_sumが関数sumを返すと、関連パラメータおよび変数は、「クローズドパッケージ」と呼ばれる関数に保存される.
注意:戻り関数は、ループ変数やその後に変化する変数を参照しないでください.
次のようになります.
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

結果は次のとおりです.
>>> f1()
9
>>> f2()
9
>>> f3()
9

匿名関数
キーワードlambdaは匿名関数を表し、コロンの前のxは関数パラメータを表す.匿名関数には、returnと書かずに式が1つしかないという制限があります.戻り値は式の結果です.
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

デコレーション
コード実行中に機能を動的に追加する方法を「デコレータ」(Decorator)と呼ぶ.本質的にdecoratorは関数を返す高次関数である.
ログを印刷できるdecoratorを定義します.次のように定義できます.
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

上記のlogを観察すると、decoratorであるため、パラメータとして関数を受け入れ、関数を返します.Pythonの@構文を使用して、decoratorを関数の定義に配置します.
@log
def now():
    print('2015-3-25')

>>> now()
call now():
2015-3-25
@lognow()関数の定義に置くと、文:now = log(now)now変数が新しい関数を指すことに相当します.
decorator自体がパラメータを入力する必要がある場合は、decoratorを返す高次関数を記述する必要があります.書くともっと複雑になります.たとえば、logのテキストをカスタマイズするには、次のようにします.
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

この3層ネストのdecoratorの使い方は以下の通りです.
@log('execute')
def now():
    print('2015-3-25')

>>> now()
execute now():
2015-3-25

2層ネストのdecoratorと比較して、3層ネストの効果はこうです:>>> now = log('execute')(now)問題があります.decorator装飾後の関数は、__name__が元の'now'から'wrapper'に変わりました.
>>> now.__name__
'wrapper'

Pythonに内蔵されているfunctools.wrapsは、関数name属性をコピーするために使用されます.
import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

または、パラメータ付きのアクセサリーについて:
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

バイアス関数
Pythonのfunctoolsモジュールは多くの有用な機能を提供しており、そのうちの1つがバイアス関数(Partial function)である.1つの関数のいくつかのパラメータを固定(つまりデフォルト値を設定)し、新しい関数を返します.この新しい関数を呼び出すのはもっと簡単です.
バイアス関数を作成すると、実際には、関数オブジェクト、*args**kwの3つのパラメータを受信できます.
例えばint()関数を使ってバイナリ文字列を変換すると、本来の書き方はint(x, base=2)で、量が大きいと面倒なので、このように書くことができます.
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

上のin2 = functools.partial(int, base=2)は、
kw = { 'base': 2 }
int('10010', **kw)

上一篇:Python学习のモジュール