Python入門(九)関数-閉パッケージ

3469 ワード

Pythonでは、関数も変数タイプであり、変数で関数を保存することができます.
def hello():
    print("hello")

print(type(hello))

>>> <class 'function'>
#          func,  func   hello       
func = hello
func() #    

>>> hello

上から分かるように、関数を変数に割り当てると、この変数は関数オブジェクトを指します.もちろん、helloが実行する関数オブジェクトを変更することもできます.たとえば、次のようにします.
def say_hi():
    print("Hi")
    
hello = say_hi
hello()

>>> Hi

say_をhi関数オブジェクトにhelloを割り当てると、helloはsay_を指します.hi関数オブジェクトは,元の関数オブジェクトを指さすことなく,元の関数オブジェクトを呼び出すこともできない.
関数の上記の特性に基づいて、私たちは簡単に関数機能テーブルを実現することができます.例えば、私たちがよく見ているhttpのサービスキュー要求の処理は、要求の方法によってそれぞれ処理されます.
def handle_http_get():
    print('handle http get request')

def handle_http_post():
    print('handle http post request')

def handle_http_put():
    print('handle http put request')

http_handler = {'get': handle_http_get, 'post': handle_http_post, 'put': handle_http_put}

#         http get,post,put  

#       get ,        :
method = 'get'
http_handler[method]()

>>> handle http get request

    2.クローズドクローズ
関数がオブジェクトである以上、関数に関数オブジェクトを返すことができます.
def get_func():
    def func():
        print('inside func')

    return func

f = get_func() #   f   func    
f() #  func    

>>> inside func

1つの関数がその環境変数と結合すると、Closureが構成されます.
def power_factory(n):
    def power(list_arg):
        for i in range(len(list_arg)):
            list_arg[i] = list_arg[i]**n

    return power

#  list        
list1 = [1, 2, 3]
f1 = power_factory(2)
f1(list1)
print(list1)
f1(list1)
print(list1)

#  List       
list1 = [1, 2, 3]
f2 = power_factory(3)
f2(list1)
print(list1)

>>> 
[1, 4, 9]
[1, 16, 81]
[1, 8, 27]

Power関数オブジェクトの場合、Power_factory関数が渡すパラメータnはその環境変数であり、関数オブジェクトの__に保存されるclosure__ダイアログを呼び出すこのようにf 1関数を呼び出すたびに2の二乗操作が実行されるので、上から2回連続してf 1が呼び出され、出力はすべて二乗数である.キューブ操作を実行する必要がある場合は、powerを再呼び出すだけです.factoryは,環境変数n=3の閉パケットを生成する.
一般的に、cプログラミングの関数のように、ステータスはありません.c関数でstatic変数を使用してステータスを保存しない限り、閉パッケージを使用すると、関数に独自の環境変数があることを容易にすることができます.
    3. デコレーション
関数オブジェクトには__があります.name__属性、関数の名前を表します.
print(max.__name__)
>>> max

前にhello関数を実装したように、hello関数の機能を強化し、hello関数を実行する前に印刷デバッグ情報を追加したいと考えています.hello関数のソースコードを変更することなく、パケットを閉じることで完了できます.
def debug(func):
    def wrapper(*args, **kw):
        print('call %s' % func.__name__)
        return func(*args, **kw)

    return wrapper

hello = debug(hello)
hello()

>>> 
call hello
hello

上記の使用過程では、hello=debug(hello)を先に実行する必要があり、感覚コードは常に変な感じがするため、Pythonに@構文を導入し、使用を簡略化する.
@debug
def hello():
    print(‘hello')
    
hello()
>>>
call hello
hello

@debugをhelloの前に置くと、hello=debug(hello)が実行されることになります.
Debugでパラメータを渡す必要がある場合は、3階層関数定義を使用します.
def debug(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s: call %s' % (text, func.__name__))
            func(*args, **kw)
        return wrapper
    return decorator

@debug('debug_info')
def hello():
    print("hello")

hello()

>>>
debug_info: call hello
hello

@debug('debug_info')をhelloの前に置くことは、hello=debug('debug_info')(hello)を実行したことに相当します.
    
やっと書き終わって、眠くなって、寝ました.