Python 3オブジェクト向け:インスタンス(instance)

12359 ワード

クラスがデータ構造の定義である場合、インスタンスはそのタイプの変数を宣言します.Python 3.xのデフォルトのすべてのクラスは新しいクラスであり、タイプのインスタンスはこのタイプのオブジェクトであり、新しいクラスを定義し、新しいクラスを作成する.
インスタンスの作成
ほとんどのオブジェクト向け言語では、キーワードnewを提供してクラスのインスタンスを作成する.Pythonはより簡単で、関数呼び出しの形式でクラスの初期化とインスタンスの作成を完了する.
class MyClass():
    pass
#          
mc = MyClass()

_init()メソッド(コンストラクタconstructor)
インスタンスを作成すると、クラスはクラスのインスタンスオブジェクトを作成するように呼び出され、Pythonは_init()が実装されているかどうかをチェックします.デフォルトでは、_init()を書き換えていない場合は、デフォルトの操作を実行し、デフォルトのインスタンスを返します.インスタンスに初期のデータ属性を追加する操作が必要な場合は、クラスの定義に特殊なメソッド_init()を書き換える必要があります.クラスの定義に特殊なメソッド_init()を書き換えると、クラスのインスタンスを作成した後に呼び出され、インスタンスオブジェクトが最初のパラメータselfとして_init()に入力され、クラスの初期化とインスタンスの作成が完了します._init()メソッドはクラス定義の特殊なメソッドの1つであり、デフォルトでは何も行われません.いくつかのクラスの属性をカスタマイズする必要がある場合は、特殊な方法を書き換え、デフォルトの動作を上書きします.
_new()メソッド(コンストラクタ)
クラスの特殊な方法_new()[静的な方法]は、実際には特殊な方法init()と同様に、クラスのインスタンスに特定の操作を追加する必要がある場合に、これらの特殊な方法を書き換えることによって実現される.相違点は、init()メソッドは、objectベースクラスから継承するクラスに対して用いる特殊なメソッドである.new()メソッドは、ユーザがPythonの組み込みタイプを派生させるために用いる特殊なメソッドである.例えば、文字列タイプ、浮動小数点タイプデータを派生させる場合、new()メソッドクラス初期化クラスを用いる.new()メソッドは、親クラスのnew()作成オブジェクトを呼び出す.
_del()メソッド(デフォーマdestructor)
Pythonのゴミ回収メカニズムは参照カウントによって実現するため、1つのインスタンスのすべての参照がクリアされると、_del()メソッドが呼び出される.
class P():
     def __del__(self):
            print('deleted')
class L(P):
    def __init__(self):
        print('initialized')
    def __del__(self):
        P.__del__(self)  #      __del__  
#    ,    ,  initialized,  __init__()
c1 = L()
#         
c2 = c1
c3 = c1
#     id()                 
print(id(c1),id(c2),id(c3))
initialized
139950121340488 139950121340488 139950121340488
del c1
del c2
del c3 #                  ,__del__()   
deleted

まとめ:デフォーマは一度だけ呼び出され、参照カウントが0になるとオブジェクトはクリアされます.親から派生した新しいクラスは、デフォーマを書き換えるときに、まず親のデフォーマを呼び出すべきです.呼び出しdel c 1は、呼び出したdel()を表さず、_del()は常に暗黙的に呼び出されます.インスタンスオブジェクトを循環参照すると、カウントが増加します._del()は呼び出されません._del()未キャプチャの異常は無視される可能性があります.デフォーマが呼び出されたときに変数の一部が削除された可能性があります.デフォーマが書き換えられ、インスタンスがループの一部である場合、ゴミ回収メカニズムはこのループを終了しません.表示する必要がある呼び出しデフォーマ
インスタンスのトレース
Pythonではオブジェクト参照のカウントメカニズムがあるが、インスタンスに対して作成する個数をカウントしていないため、1つのクラスの何個のインスタンスが作成されたかを知るには、この機能を手動で追加する必要があり、_init(),_del()メソッドを上書きすることで実現できる.静的クラスメンバー変数を用いてカウントする.
class InstCount():
    count = 0     #   

    #         ,   count +1
    def __init__(self):
        InstCount.count += 1  

    def __del__(self):
        InstCount.count -=1

    #       
    def howMany(self):
        return InstCount.count
a1 = InstCount()
a2 = InstCount()
a3 = InstCount()
a1.howMany()
3
del a2
print('InsCount.count=%d, a1.howMany():%d'%(InstCount.count, a1.howMany()))
InsCount.count=2, a1.howMany():2
del a3
del a1
print('InsCount : %d'%InstCount.count)
InsCount : 0

インスタンスのプロパティ
インスタンスのメソッド属性は親から継承するものであり、データ属性は親から継承してもよいし、インスタンス作成後に任意に設定してもよい.クラス定義において_init()にインスタンスの属性を設定してもよい.静的タイプの言語ではすべての属性が使用前に明確な宣言と定義が必要である.動的言語Pythonとして、インスタンスのプロパティは動的に作成できます.この動的言語の利点は欠陥でもあります.条件文に属性が作成すると、条件文は実行されない可能性があり、属性も存在しないため、この属性にアクセスするとAttribute異常が放出されるので注意が必要である.
コンストラクタでインスタンス属性を設定インスタンス作成時に最初に呼び出す方法は_init()であり、コンストラクタの実行が完了するとインスタンスオブジェクトに戻り、インスタンス化が完了する.インスタンスオブジェクトは自動的にインスタンス化後に返されるので、コンストラクタはオブジェクトを返さない.コンストラクタでは通常の関数と同様にデフォルトパラメータを設定することができる.これにより、インスタンスを作成する際にコンストラクタに値を明示的に渡す必要はなくなりますが、データ属性を変更する必要がある場合には、新しい値を明示的に渡すことでデフォルト値を上書きすることもできます.次は、ある賃貸住宅で販売税8.5%、部屋税10%を支払うと仮定した賃貸住宅の例です.毎日の家賃はデフォルト値を捨てません.
class HotelRoomCalc():
    def __init__(self, rt, sales=0.085, rm=0.1):
        self.roomRate = rt
        self.salesTax = sales
        self.roomTax = rm
    def calcTotal(self, days=1):
        daily = round(self.roomRate*(1+self.salesTax+self.roomTax), 2)
        return float(days)*daily
#    
f1 = HotelRoomCalc(299)
f1.calcTotal()
354.31
f1.calcTotal(100)
35431.0
#    ,          
f2 = HotelRoomCalc(200, 0.25, 0.15)
f2.calcTotal()
280.0

インスタンス属性とクラス属性は、組み込み関数dir()を使用してすべてのインスタンス属性を印刷できます.
print(dir(f1))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'calcTotal', 'roomRate', 'roomTax', 'salesTax']

インスタンスもクラスのdict属性を継承する
print(f1.__dict__)  # vars()         
{'roomRate': 299, 'salesTax': 0.085, 'roomTax': 0.1}

変更__dict_クラスとインスタンスに対して、_dict属性は修正可能であるが、非常に明確な目的がない限り、このような修正はOOPを破壊し、いくつかの副作用をもたらす可能性がある.もし_dictを修正しなければならないならば、_setattr()メソッドを書き直して実現することを提案しない.setattrメソッド自体を上書きすることは冒険である.例えば、無限の再帰とインスタンスオブジェクトを破壊する.
組み込みタイプとインスタンス:組み込みタイプはPythonが持参したデータ型、リスト、辞書、浮動小数点数、整数、浮動小数点数、複数などである.組み込みタイプはカスタムタイプと同様にdir()とともにクラスインスタンス属性を表示することができ、組み込みタイプは_dict_ツールバーの
#         
x = 2+0.3j
type(x), x.__class__
(complex, complex)
print(dir(x))
['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', 'conjugate', 'imag', 'real']
print("x's imag:%.1f, x's real:%.1f"%(x.imag, x.real))
x's imag:0.3, x's real:2.0
#   
print("x's conjugate:",x.conjugate())
x's conjugate: (2-0.3j)

インスタンス属性.クラス属性
インスタンス属性は動的属性であり、いつでも追加、削除、修正が可能であり、クラスのデータ属性は静的メンバーのように参照され、複数回のインスタンス化ではクラスデータ属性は変わらない.インスタンスはクラス属性にアクセスでき、クラスの属性を変更せず、クラス属性を変更するにはクラス名が必要である.インスタンスに同名の属性があるとクラス属性が上書きされ、クラス名でクラス属性にアクセスできる.
class C():
    x = 1
c1 = C()
c1.x = 2
#      
c1.x
2
del c1.x 
c1.x   #          
1
#      ,     
C.x = 3
c1.x
3

クラス属性が可変の場合
(クラス属性は辞書タイプ)
class P():
    d = {1:'dog'}
c = P()
c.d
{1: 'dog'}
c.d[2]='cat'
c.d
{1: 'dog', 2: 'cat'}
P.d  #        
{1: 'dog', 2: 'cat'}
del c.d
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

 in ()
----> 1 del c.d


AttributeError: d

AttributeErrorは、インスタンスcが同じ名前のプロパティを作成していないため、クラスから継承されたプロパティだけです.