***

7765 ワード

関数クローズ
定義#テイギ#
役割ドメインを拡張した関数(定義体以外で定義された非グローバル変数にアクセス可能
さぎょう
  • 変数を共有するときに不安全なグローバル変数
  • を使用することを避ける.
  • では、レイアウトオブジェクトへのプログラミングを簡略化する
  • と同様に、関数をいくつかのデータに関連付けることができる.
  • 同じコードが生成するたびに閉じたパケットは、その延びる役割ドメインが互いに独立する(カウンタ、レジストリ)
  • である.
  • 関数の一部の動作は、作成時に予知できず、動的に実現する必要があるとともに、インタフェースの一貫性を維持したい
  • である.
  • より低いメモリオーバーヘッド:クラスのライフサイクルは閉パッケージ
  • よりはるかに大きい.
  • インプリメンテーション
  • コード#コード#
    print("Class  :")
    class Averager:
        def __init__(self):
            self.series = []
        def __call__(self,new_val):
            self.series.append(new_val)
            return sum(self.series)/len(self.series)
    avg1 = Averager()
    print(avg1(3))
    print(avg1(2))
    
    print("    :")
    def Avg_1():
        count = 0
        total = 0
        def Avg_2(val):
            nonlocal total,count
            total+=val
            count+=1
            return total/count
        return Avg_2
    avg = Avg_1()
    print(avg(9))
    print(avg(10))
    '''
      
    Class  :
    3.0
    2.5
        :
    9.0
    9.5
    '''

    理解する
    機能の説明
    このコードで解決する必要があるのは、average関数を定義し、値を渡すたびに、この値と以前の入力値の平均値を得ることができます.たとえば,1回目が1,平均値が1,2回目が2,平均値が1.5のように推定される.
    クラスモード
    1つ目の方法はクラスを構築することです.これも私たちが一般的に考えやすい方法です.クラスにリストを作成し、呼び出すたびに新しい値appendを入れます.これは解決方法です.
    関数クローズドパッケージ方式
    ここでは,前述した役割ドメインに関連し,関数閉パケットが役割ドメインを延長しているが,我々の外層関数は2つの変数を格納するためだけであり,他の役割はないことが分かる.実はこの時疑問があるはずです.Avgを呼び出しています.1()以降、countとtotalがLovalレイヤにあるため、関数呼び出しが終了して破棄されるべきですが、実際にはありません.Avg_2ではnolocalキーワードにより2つの変数のライフサイクルが延長され、呼び出すたびに2つの変数にアクセスでき、効果が得られます.
    デコレーション
    なぜアクセサリーというものが現れたのか
  • 名称管理
  • 表示呼び出し
  • 近接原則
  • 完全多重
  • @文法糖
    '@'は関数の修飾子として使用され、モジュールまたはクラスの定義層内で関数を修飾することができ、関数定義の前の行に表示され、関数定義と同じ行には許可されません.
    デコレーションとは
  • アクセラレータは呼び出し可能なオブジェクトであり、関数の機能
  • を何らかの方法で強化する.
  • 装飾器は文法糖であり、ソースコードに関数(このソースコードはコンパイル後のソースコードを指す)
  • をマークする.
  • 解釈器は、ソースコードを解析する際に、装飾された関数を第1の位置パラメータとして装飾器
  • に伝達する.
  • デコレーションは、被デコレーション関数を直接処理し、それを返す(一般的には属性のみを変更し、コードを変更しない)
  • .
  • デコレラは、被デコレーション関数を新しい関数または呼び出し可能なオブジェクトで置き換えることもできる(ただし、コア機能は一般的に変わらない)
  • .
  • 装飾器は閉パッケージのように見えるだけで、実は機能の位置決めと閉パッケージが重なるのも大きな違いがあります
  • .
  • 装飾器モードの本質はメタプログラミングである:実行時にプログラム動作を変更する
  • デコレーションの無視できない特性:モジュールのロード時に直ちに
  • を実行する
  • の装飾器は積層可能であり、底から上へ1つずつの装飾
  • が施されている.
  • デコレーションはパラメータ付きでよいが、このとき少なくとも2つのデコレーション
  • と書く.
  • 装飾器のよりPythonicの実現方式は、実はクラスにおいてcall()メソッド
  • を実現する.
    コード#コード#
    def check_param(**kw):
        flag = kw.get('flag')
        def check_p(func):
            def decorate(*args):
                if flag:
                    if not all([isinstance(arg,int) for arg in args]):
                        raise TypeError("{} only accepts integers as argument".format(func.__name__))
                return func(*args)
            return decorate
        return check_p
    
    @check_param(flag=True)
    def my_sum(a,b):
        return a+b
    
    if __name__=='__main__':
        print(my_sum(1,2))
        print(my_sum(1,2.0))
    
    '''
      
    3
    Traceback (most recent call last):
      File "/home/xueaoru/  /pydemo/blog.py", line 18, in 
        print(my_sum(1,2.0))
      File "/home/xueaoru/  /pydemo/blog.py", line 7, in decorate
        raise TypeError("{} only accepts integers as argument".format(func.__name__))
    TypeError: my_sum only accepts integers as argument
    
    '''
    

    説明する
    上のコードは検査を完了するためですmy_sum関数のパラメータが整数の機能の装飾器であるかどうか、同時にスイッチ機能を追加し、flagをtrueに設定するとチェック機能をオンにし、整数でなければ直接エラーを報告します.
    理解する
    装飾器は,関数が既存の関数の内部実装を変更することなく,既存の関数を機能増強する.一方、@構文糖は元の関数を修飾する修飾子であり、@構文糖を呼び出して修飾すると、その関数が呼び出されなくても修飾文が実行され、装飾器の実行がトリガーされるためである.このとき,この関数はパラメータとして修飾関数の外部関数に渡され,その後,この関数は参照として内部関数に付与される関数名,すなわち我々の真の操作は内部関数で行われるので,内部関数で元の関数を機能的に増強することができる.中には、パラメータがある場合は、内部関数も*と**でパケットを分解してパラメータを得る必要があります.元の関数に戻り値がある場合は、元の関数を呼び出したときにも戻り値を与えるべきです.アクセサリー自体にパラメータが付いている場合は、アクセサリー関数の外に受信パラメータのパッケージを追加してパラメータを得ることができます.
    OOP In Python
    コンセプト
    すべてが対象
    Pythonのデータ型を言語設計の面から理解する:すべてがオブジェクトであり、Objectから継承されている.Objectは、identity、type、valueの3つの部分から構成されています.
    identity
    理解する
    Objectsが作成されると、identityも破棄されるまで変更されません.c++のアドレスとの差は少ないと思いますが、もちろん完全には理解できませんし、違う方もいます.
    要点
  • 変数は作成したObjectのidentity
  • を格納する.
  • 作成された異なるObjectには、異なるidentity
  • があります.
  • 変数のidが変わったのは、Objectのidentityが変わったからではなく、対応するObjectが
  • になったからです.
  • 可変オブジェクトの場合、計算結果が既に存在する場合、同じidentity
  • を直接返すことができる.
    type
    要点
  • Objectが作成されると、そのtypeは
  • を変更しません.
  • typeは、1つのObjectがそれらの演算をサポートできることを決定し、可能な値はどの範囲
  • であるかを決定する.
    value
    要点
  • 一部のObjectのvalueは変更できます:可変オブジェクト
  • 一部Objectのvalueは変更できません:可変オブジェクト
  • 各classは定義時に継承されていない場合、objectというスーパーclassを継承し、各カスタムclassはpythonでtype objectである.
    @classmethod
    理解する
    オブジェクトに依存せずにクラス内のメソッドをこのクラスのメソッドに変更することができます.つまり、オブジェクトが作成されていないときに、このクラスのメソッドを呼び出して一定の操作を実行することもできます.これはC++の静的メンバー関数に似ています.
    コード#コード#
    class Student:
        teacher_name = "Omg"
        def __init__(self,name):
            self._name = name
        @classmethod
        def Teacher(cls):
            print(cls.teacher_name)
        def Me(self):
            print(self._name)
    if __name__== '__main__':
        aa = Student("xue")
        aa.Teacher()
        aa.Me()
        Student.Teacher()
    '''
    Omg
    xue
    Omg
    '''

    説明する
    このコードはTeacherメソッドを呼び出すことで先生の名前が得られ,オブジェクトを介して直接呼び出さなくても先生の名前を出力できることがわかる.classmethodはこの役割を果たします.
    @property
    理解する
    本質的にはこれは装飾器であり、get、set関数の対外バインドを書くのを省くことができます.
    property
    関数のプロトタイプ
    property(fget=None, fset=None, fdel=None, doc=None)

    コード#コード#
    @propertyは次のコードと同じ効果です
    class Teacher:
        def __init__(self,name,subject):
            self._name = name
            self._subject = subject
        def setName(self,name):
            self._name = name
        def getName(self):
            return self._name
        def setSubject(self,subject):
            self._subject = subject
        def getSubject(self):
            return self._subject
        def show(self):
            print("name is:{} and subject is:{}".format(self._name,self._subject))
        name = property(getName,setName)
        subject = property(getSubject,setSubject)
    if __name__ == '__main__':
        t = Teacher("A","math")
        t.show()
        t.name = "B"
        t.subject = "English"
        t.show()
    '''
    name is:A and subject is:math
    name is:B and subject is:English
    '''

    @propertyを使用した後のより美しいバージョン
    class Teacher:
        def __init__(self,name,subject):
            self._name = name
            self._subject = subject
        
        @property
        def name(self):
            return self._name
        @name.setter
        def name(self,name):
            self._name = name
        @property
        def subject(self):
            return self._subject
        @subject.setter
        def subject(self,subject):
            self._subject = subject
        
        def show(self):
            print("name is:{} and subject is:{}".format(self._name,self._subject))
    if __name__ == '__main__':
        t = Teacher("A","math")
        t.show()
        t.name = "B"
        t.subject = "English"
        t.show()

    に注意
    ここで@propertyはsetterの前で初期化しなければなりません.これは解釈器がプログラムを読むときに上から下へ読むので、理解しやすいはずです.
    Special method
    要点
  • のすべてのspecial methodは、pythonに組み込まれた関数とカスタムclassをシームレスに接続するために実装される
  • です.
  • pythonには多くの内蔵関数がありますが、これらの関数のほとんどはspecial method
  • です.
  • pythonのspecial method:https://rszalski.github.io/magicmethods/

  • コード#コード#
    class A:
        def __init__(self):
            pass
        def __str__(self):
            return "I am str"
        def __len__(self):
            return 15
        def __bool__(self):
            return False
    
    if __name__ == '__main__':
        a = A()
    
        print(a,len(a),a==True)
    

    転載先:https://www.cnblogs.com/aoru45/p/9937751.html