Pythonノート9関数式プログラミング:匿名関数、高次関数、装飾器

7054 ワード

前編では、閉パッケージは関数式プログラミングの体現の一つにすぎません.
Lambda式(匿名関数)
lambda parameter_list: expression    #     ,  return

匿名関数の定義と呼び出し:
def add(x, y):
    return x + y

f = lambda x,y: x+y     #         ,        

print(add(1,2))
print(f(1,2))

#3
#3

Lambdaでは単純な式操作しかできず,付与操作はできない.
さんげんしき
実質的には、式バージョンのif else文
フォーマット:条件が真の場合に返される結果if条件判断else条件が偽の場合に返される結果
x = 2
y = 1
r = x if x > y else y
print(r)
#x > y ? x : y        #        

#2

map
関数式プログラミングの思想に基づいて、使用を推薦して、1つのクラスです
map(関数、シーケンス)
シーンの使用:シーケンス内のすべての値を関数に順次入力し、戻り結果を順次受信してlistを構成します.数学的に見るとmapはマッピングに相当し,元のリストを結果リストに一つ一つマッピングする.
指定されたリストの各項目に対して平方を求め、リストに存在します.
list_x = [1,2,3,4,5,6,7]

def square(x):
    return x * x

r = map(square, list_x)
print(list(r))

#[1, 4, 9, 16, 25, 36, 49]

mapがlambdaと組み合わせて使用される場合、正しい開き方です.
mapとlambda
両者を結合して、平方を求めます:(関数は1つのパラメータしかありません)
list_x = [1,2,3,4,5,6,7]

r = map(lambda x:x*x, list_x)
print(list(r))

#[1, 4, 9, 16, 25, 36, 49]

非常に簡潔である.
2つのパラメータのリストを入力:
list_x = [1,2,3,4,5,6,7]
list_y = [1,2,3,4,5,6,7]

r = map(lambda x, y : x*x + y, list_x, list_y)
print(list(r))

#[2, 6, 12, 20, 30, 42, 56]

reduce
関数です
連続的な計算を行い、lambda式を連続的に呼び出します.
reduceの下の関数には必ず2つのパラメータがあります.
from functools import reduce

list_x = [1,2,3,4,5,6,7]
r = reduce(lambda x,y:x + y, list_x)
print(r)

#28
#    ((((((1+2)+3)+4)+5)+6)+7)

何を続けるかはlambdaが決定し,加算できるだけではない.
最後のビットは初期値を設定でき、最初の計算で計算されます.
from functools import reduce

list_x = [1,2,3,4,5,6,7]
r = reduce(lambda x,y:x + y, list_x, 10)
print(r)

#38

ビッグデータ計算モデル:map/reduceプログラミングモデル、マッピング/集約パラレル計算を解決します.
pythonにおける関数式プログラミングの重要な体現はmap,reduceにある
filter
filterはルールに合わないデータをフィルタリングすることができます.
除外シーケンスの0は1だけ保持されます.
list_x = [1,0,1,0,0,0,1,1]
r = filter(lambda x:True if x == 1 else False, list_x)
print(list(r))

#[1, 1, 1, 1]

フィルタが値を返すのは真と偽でなければフィルタリングが完了しません(TrueとFalseを表すことができる限り)
以下に簡略化できます.
list_x = [1,0,1,0,0,0,1,1]
r = filter(lambda x: x, list_x)
print(list(r))

#[1, 1, 1, 1]

指定したシーケンスの大文字を削除します.
import re

list_x = ['a', 'A', 'b', 'B', 'C', 'z']
r = filter(lambda x : re.findall('[a-z]', x), list_x)
print(list(r))

#['a', 'b', 'z']

findall関数はアルファベットが見つからない場合は[]を返し、Falseです.小文字が見つかったら['a']などを返します.Trueです.
コマンドプログラミングvs関数プログラミング
コマンドプログラミングはdef if else forに関連する
関数式プログラミングはmap reduce(置換サイクル)、filter、lambda(基本ユニット、def対応)に関する.
map reduce filterは理論的にdef if else forを置き換えることができる
関数式プログラミングの元祖:lisp言語、人工知能分野の応用が多い.
Pythonは関数式プログラミングをサポートしていますが、本質的にはコマンド式プログラミングであり、一部は関数式プログラミングをサポートしています
デコレーション
最も多くの高次知識を用いる.Flaskなどのフレームワークには装飾器が多く含まれています
導入:単純な関数を指定します.
import time

def f1():
    print('This is a function')

f1()

上記の関数では、新しい需要があり、出力時間は、次のように変更されます.
import time

def f1():
    print(time.time())      #unix    
    print('This is a function')

f1()

#1557226254.0117128
#This is a function

上のコードは機能を実現しているが,修正に対しては閉鎖的であり,拡張に対しては開放的である(開閉原則)という原則に反している.
また、何百もの関数にこの需要がある場合、コードを付けるのは現実的ではありません.
最適化:
import time

def f1():
    print('This is a function')

def f2():
    print('This is a function')

def print_current_time(func):       #          
    print(time.time())
    func()

print_current_time(f1)
print_current_time(f2)

#1557226686.7066443
#This is a function
#1557226686.70715
#This is a function

関数式プログラミングの思想を巧みに運用し、関数をパラメータとして伝え、開閉の原則を守った.優雅さが足りない...元の関数を出力時間機能にバインドしていません.先に出力する時間に相当し、文を実行し、関連性がありません.
装飾器には、元の関数と新しい機能をバインドし、元の関数の機能の増加を体現しているが、元の関数の内部の実現を修正しないという利点がある.
デコライザの最適化を使用すると、次のようになります.
import time

def decorator(func):            #  
    def wrapper():          #   
        print(time.time())
        func()
    return wrapper

@decorator            #         
def f1():
    print('This is a function')

@decorator
def f2():
    print('This is a function')

f1()
f2()

#1557227957.0940094
#This is a function
#1557227957.0950105
#This is a function

Pythonの中の装飾器が採用したAOPのプログラミング思想
関数にパラメータがある場合、wrapperはパラメータを入力する必要があります.
import time

def decorator(func):            
    def wrapper(func_name):          #        ,   
        print(time.time())
        func(func_name)            #   
    return wrapper

@decorator
def f1(func_name):    
    print('This is a function:' + func_name)

f1('test_func')

#1557228383.601304
#This is a function:test_func

アクセラレータは汎用性があり、複数の関数が異なる数のパラメータを受け入れる場合は、可変パラメータを使用して最適化します.
import time

def decorator(func):            
    def wrapper(*args):         #             
        print(time.time())
        func(*args)             #       
    return wrapper

@decorator
def f1(func_name):      #    
    print('This is a function:' + func_name)

@decorator
def f2(func_name1, func_name2):     #    
    print('This is a function:' + func_name1)
    print('This is a function:' + func_name2)

f1('test_func')
f2('test_func1', 'test_func2')


#1557228899.3838246
#This is a function:test_func
#1557228899.3843257
#This is a function:test_func1
#This is a function:test_func2

*argsは**キーワードパラメータをサポートしていません
関数にキーワードパラメータが表示されると、次のように最適化されます.
import time

def decorator(func):            
    def wrapper(*args, **kw):         #             
        print(time.time())
        func(*args, **kw)             #        
    return wrapper

@decorator
def f1(func_name):      #    
    print('This is a function:' + func_name)

@decorator
def f2(func_name1, func_name2):     #    
    print('This is a function:' + func_name1)
    print('This is a function:' + func_name2)

@decorator
def f3(func_name1, func_name2, **kw):     #       
    print('This is a function:' + func_name1)
    print('This is a function:' + func_name2)
    print(kw)

f1('test_func')
f2('test_func1', 'test_func2')
f3('test_func1', 'test_func2', a = 1, b = '2', c = '123')

# 1557229295.4020875
# This is a function:test_func
# 1557229295.4020875
# This is a function:test_func1
# This is a function:test_func2
# 1557229295.4030857
# This is a function:test_func1
# This is a function:test_func2
# {'a': 1, 'b': '2', 'c': '123'}

以上のように、アクセサリーの使い方は完璧です
pythonでは、関数定義時にいくつかのパラメータがあるかにかかわらずfunc(*args,**kw)で呼び出すことができます.
アクセサリーのまとめ:
  • あるパッケージユニットを修正したい場合は、アクセサリーを付けることができます.
  • は、コード実装を破壊する必要がなく、コード多重化が容易である.

  • 1つの関数には複数の装飾器があります.
    認証が必要な関数に専用の装飾器などの用途を加える.
    装飾器はAOP思想を体現する