Pythonステップアップ-アクセサリー

15913 ワード

この章は、次の3つの部分に分かれています.
  • 関数役割ドメイン
  • 閉パッケージ
  • デコレーション
  • 関数のスコープ
    関数内部役割ドメインlocal>関数内部と埋め込み関数間enclosing>グローバル役割ドメインglobal>内蔵役割ドメインbuild-in
    次に例を示します
    SCORE = 60 #100     
    
    def check(score):
        if score >= SCORE:
            print('A')
        else:
            print('B')
    
    SCORE = 60 #100     
    
    def check(score):
        if score >= SCORE:
            print('A')
        else:
            print('B')
    
    if __name__=='__main__':
        check(90)
    #    
    A

    説明:まず内部役割ドメインを検索し、SCOREの定義はありません.その後、関数も埋め込み関数を使用しません.その後、グローバル領域を検索してSCOREを見つけ、使用します.また、たとえばlen、max、minなどの関数python標準ライブラリでは、内蔵のbuild-inに属し、直接呼び出すことができますが、最後のステップまで呼び出されません.
    インライン関数
    1つの関数の内部定義では、この関数のみが使用できます.
    SCORE = 60 #100     
    
    def check(score):
        if score >= SCORE:
            print('A')
        else:
            print('B')
        def print_score(): #      
            print(score) 
    
        print_score() #      
    
    if __name__=='__main__':
        check(90)
    #    
    A
    90

    クローズドパッケージ
    Closure:内部関数でenclossing役割ドメインの変数を参照します.pythonでの関数の実質と属性について説明する必要があります.
  • 関数はオブジェクト
  • です.
  • 関数の実行が完了すると、内部変数は
  • に回収される.
  • 関数は、属性
  • を有する.
  • 関数は、戻り値
  • を有する.
    関数はオブジェクトで、別の変数にコピーできます.
    Max = max #python    
    print(Max(3,2))
    > 3

    例を見てみましょう
    SCORE = 60 #100     
    
    def check(score):
        if score >= SCORE:
            print('A')
        else:
            print('B')
        def in_check():
            print('score:',score)
    
        #           
        print(in_check.__closure__)
        in_check()
        return in_check
    
    if __name__=='__main__':
        func = check(90)
        print('---------------------------')
        func()
        print('---------------------------')
        print(func.__closure__) #           
    #    
    A
    (0x0000000002277498: int object at 0x000000005322AF80>,)
    score: 90
    ---------------
    score: 90
    ---------------
    (0x0000000002277498: int object at 0x000000005322AF80>,)

    印刷結果から、次の結論が得られます.
  • func()はin_check()
  • in_check()には変数scoreが使用され、func()で使用されているのと同じ変数が使用されています.内部変数が回収されていないのは、関数の参照カウントが0
  • ではないためです.
    クローズドパッケージの役割
    かばんを閉じると言ったが、彼は何の役に立つのだろうか.まず例を見てみましょう
    SCORE_90 = 90  #150      90
    SCORE_60 = 60  #100      60
    
    def check_150(score):
        if score > SCORE_90:
            print('A')
        else:
            print('B')
    
    def check_100(score):
        if score > SCORE_60:
            print('A')
        else:
            print('B')
    
    if __name__=='__main__':
        check_150(78)
        check_100(78)
    #    
    B
    A

    ここでまた120点の制度があれば、コードを追加したり、Aレベルを総点数の80%に上げたりして、変えるのは面倒です.
    したがって,閉包法を用いることは容易であり,これは2次元の変化を制御することに相当し,分数線の変化と比較が必要な分数の変化を同時に受け入れることができる.
    def set_aver_score(score):
        def cmp(val):
            if val > score:
                print('A')
            else:
                print('B')
    
        return cmp
    
    if __name__=='__main__':
        f_100 = set_aver_score(60)
        print(f_100.__closure__, type(f_100))
        f_100(86)
        f_100(59)
    #    
    #    f_100           score,          
    (0x0000000002857498: int object at 0x0000000050CEABC0>,) 'function'>
    A
    B

    これは,パッケージング性とコード多重性を体現している.
    クローズドパッケージの使用例
    もし私たちが今和を求める関数が必要なら.
    def my_sum(*args):
        print('sum!')
        return sum(args)
    
        my_sum(1, 2, 3, 4, 5, 6)
        my_sum(1, 2, 3, 4, 5, 'A')
    #    
    TypeError: unsupported operand type(s) for +: 'int' and 'str'

    パラメータのチェックがないため、実行には明らかにTypeErrorがあります.同様に、平均数を求める関数があれば、strタイプのパラメータを要求することはできません.そうすると、2つのタイプのチェックコードを書く必要があります.だから、簡略化すべきではないでしょうか.
    def my_sum(*args):
        print('sum!')
        return sum(args)
    
    def dec(function):
        print('dec')
        def in_dec(*args):
            print('in_dec')
            if len(args) == 0:      #   
                return 0
            for val in args:
                if not isinstance(val, int):    #              ,      return
                    return 0
            print('return function(*args)', function.__name__)  #  function   
            return function(*args)      
    
        print('return in_dec')
        return in_dec
    
    if __name__=='__main__':
    
        my_sum = dec(my_sum)                    #  1
        print(type(my_sum), my_sum.__name__)    #  2
    
        print('--------------')
        my_sum(1, 2, 3, 4, '5')                 #  3
        print('--------------')
        my_sum(1, 2, 3, 4, 5)                   #  4
    
    #    
    dec
    return in_dec
    'function'> in_dec
    --------------
    in_dec
    --------------
    in_dec
    return function(*args) my_sum
    sum!

    分析実行プロセス:ステップ1:dec(my_sum)でmy_sum関数はパラメータとして入力され、print(‘dec’)を印刷し、in_を定義します.dec埋め込み関数を実行し、印刷print(「return in_dec」)を実行し、in_を返します.dec.そしてin_decはmyに値を割り当てますsum、特に今のmyに注意sumはもう元のmyじゃないsumです.これはステップ2の印刷からもわかりますが、タイプが変わりました.ステップ3:今my_sumは実はin_dec従って実行コードは、パラメータが直接returnステップ4:print(‘in_dec’)を正常に印刷し、文が一致していると判断してprint(‘return function(*args)’,function.)を印刷するname__),注意この時点でfunctionは元のmy_sum(また帰ってきた!)、最後にパラメータを入力し、結果を計算し、結果を返します.
    ここで私たちは一周しました.つまりmy_に相当します.sumは、元のコードを変更する必要がなく、他の関数も使用できる追加の判断コードを追加しました.
    デコレーション
  • デコレーション関数
  • をデコレーションするために使用される
  • は、関数オブジェクト
  • を返します.
  • が装飾する関数識別子は、返される関数オブジェクト
  • を指す.
  • 構文糖@dec
  • コードの例:
    def dec(function):
        print('dec')
        def in_dec(*args):
            print('in_dec')
            if len(args) == 0:      #   
                return 0
            for val in args:
                if not isinstance(val, int):    #              ,      return
                    return 0
            print('return function(*args)', function.__name__)  #  function   
            return function(*args)
    
        print('return in_dec')
        return in_dec
    
    @dec
    def my_sum(*args):
        print('sum!')
        return sum(args)
    
    
    if __name__=='__main__':
    
        print('__main__')
        print(type(my_sum), my_sum.__name__)
        res = print(my_sum(1, 2, 3, 4, '5'))
        print(res)
        print('--------------------------')
        res = my_sum(1, 2, 3, 4, 5)
        print(res)
    
    #    
    dec
    return in_dec
    __main__
    'function'> in_dec
    in_dec
    0
    None
    --------------------------
    in_dec
    return function(*args) my_sum
    sum!
    15

    main関数の最初の文を実行する前に、アクセサリーが実行されていることがわかります.つまりこの時my_sumは既に置き換えられています.次にコード実行は以前と同じです.