Pythonの研究ノート(7) - マジックメソッド

1.建設と破壊が行われ

魔法の方法は、2つのアンダースコアで囲まれています

__init__()方法

__init__この方法は、デフォルトパラメータ、戻り値なしではありません。オーバーライド機能をクリアするために必要なクラスオブジェクトの初期化手順の例

>>> class Rectangle:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def getPeri(self):
        return (self.x+self.y)*2
    def getArea(self):
        return self.x * self.y


>>> rect = Rectangle(3,4)
>>> rect.getPeri()
14
>>> rect.getArea()
12
>>> #init返回值一定是None
>>> class A:
    def __init__(self):
        return "A"


>>> a = A()
Traceback (most recent call last):
  File "", line 1, in 
    a = A()
TypeError: __init__() should return None, not 'str'

__new__()方法

__new__()オブジェクトのインスタンスを作成する際の方法は、オブジェクトのインスタンスを返す、パラメータは、CLSは、最初のメソッドが呼び出されています

>>> class CapStr(str):
    def __new__(cls,string):
        string = string.upper()
        return str.__new__(cls,string)


>>> a = CapStr("I love FishC.com")
>>> a
'I LOVE FISHC.COM'

__del__()方法

__del__()オブジェクトが破棄されようとしているときにメソッドが呼び出されます

>>> class C:
    def __init__(self):
        print("我是init方法,我被调用了")
    def __del__(self):
        print("我是del方法,我被调用了")

>>> c1 = C()
我是init方法,我被调用了
>>> c2 = c1
>>> c3 = c2
>>> del c3
>>> del c2
>>> del c1
我是del方法,我被调用了

オブジェクトの生成後、それに対するすべての参照は、デルとなっている、ガベージコレクションのメカニズムを開始します

ガベージコレクションについて

2.算術

演算子 魔法の対応方法 中国のコメント
+ __追加__(自己、他) 追加
- __サブ__(自己、他) 引き算
* __ MUL __(自己、他) 乗算
/ __ truedivの__(自己、他) 真の除算
// __ floordivの__(自己、他) 整数除算
__ MODの__(自己、他) モジュロ除算
divmod(A、B) __ divmodの__(自己、他) 除数と余り合成操作の結果
** __ POW __(自己、他の[モジュロ]) 剰余再度電源を取る以外の自己
<< __ LSHIFTの__(自己、他) ビット単位の左シフト
>> __ RSHIFTの__(自己、他) ビット単位の右シフト
__と__(自己、他) ビット単位のAND演算
^ __のXOR __(自己、他) ビット単位のXOR演算(同じことが0である、1 ISO)
シュウ __または__(自己、他) (1)ビット単位のOR演算

キューブの逆の操作方法

>>> class Nint(int):
    def __radd__(self,other):
        return int.__sub__(self,other)


>>> a = Nint(5)
>>> b = Nint(3)
>>> a + b
8
>>> 1 + b
2
>>> #此处执行了3-1,self是3,other是1

3.シンプルなカスタマイズ(タイマー)

時間モジュール

import time as t

class MyTimer():
    def __init__(self):
        self.unit = ['年','月','日','小时','分','秒']
        self.prompt = "未开始计时!"
        self.lasted = []
        self.begin = 0
        self.end = 0
    # 调用实例直接显示结果
    def __str__(self):
        return self.prompt

    __repr__ = __str__

    # 计算两次计时器对象之和
    def __add__(self, other):
        prompt = "总共运行了"
        result = []
        for index in range(6):
            result.append(self.lasted[index] + other.lasted[index])
            if result[index]:
                prompt += (str(result[index]) + self.unit[index])
        return prompt

    # 开始计时
    def start(self):
        self.begin = t.localtime()
        self.prompt = "提示:请先调用stop()停止计时!"
        print("计时开始")


    # 停止计时

    def stop(self):
        if not self.begin:
            print("提示:请先调用start()进行计时")
        else:
            self.end = t.localtime()
            self._calc()
            print("计时结束")

    # 内部方法,计算运行时间
    def _calc(self):
        self.lasted = []
        self.prompt = "总共运行了"
        for index in range(6):
            self.lasted.append(self.end[index] - self.begin[index])
            if self.lasted[index]:
                self.prompt += (str(self.lasted[index]) + self.unit[index])
        # 为下一轮计时初始化变量
        self.begin = 0
        self.end = 0
        print(self.prompt)

>>> t1 = MyTimer()
>>> t2 = MyTimer()
>>> t1.start()
计时开始
>>> t2.start()
计时开始
>>> t1.stop()
总共运行了1分21秒
计时结束
>>> t2.stop()
总共运行了15秒
计时结束
>>> t1
总共运行了1分21秒
>>> t2
总共运行了15秒
>>> t1+t2
'总共运行了1分36秒'

perf_counter使用する()とprocess_time()

import time as t

class MyTimer:
    def __init__(self):
        self.prompt = "未开始计时"
        self.lasted = 0.0
        self.begin = 0
        self.end = 0
        self.default_timer = t.perf_counter

    def __str__(self):
        return self.prompt
    __repr__ = __str__
    def __add__(self,other):
        result = self.lasted + other.lasted
        prompt = "总共运行了%0.2f秒" % result
        return prompt
    def start(self):
        self.begin = self.default_timer()
        self.prompt = "提示:请先调用stop()停止计时"
        print("计时开始!")
    def stop(self):
        if not self.begin:
            print("提示:请先调用start()开始计时")
        else:
            self.end = self.default_timer()
            self._calc()
            print("计时结束")
    def _calc(self):
        self.lasted = self.end - self.begin
        self.prompt = "总共运行了%0.2f秒" % self.lasted
        print(self.prompt)
        self.begin = 0
        self.end = 0

    def set_timer(self,timer):
        if timer == 'process_time':
            self.default_timer = t.process_time
        elif timer == 'perf_counter':
            self.default_timer = t.perf_counter
        else:
            print("输入无效")


t1 = MyTimer()
t1.set_timer('perf_counter')
t1.start()
t.sleep(5.2)
t1.stop()
t2 = MyTimer()
t2.set_timer('perf_counter')
t2.start()
t.sleep(5.2)
t2.stop()
print(t1 + t2)


 >>> 
计时开始!
总共运行了5.23秒
计时结束
计时开始!
总共运行了5.21秒
计时结束
总共运行了10.44秒
>>>

4.プロパティへのアクセス

マジックメソッド 意味
__ GETATTRの__(自己、名前) 利用者は中に取得し、存在しないプロパティの動作を定義しようとすると
__のgetAttributeの__(自己、名前) クラスプロパティの定義は、行動をアクセスした場合
__ SETATTRの__(自己、名前、値) 属性は、行動の集合を定義されている場合
__ delattrの__(自己、値) プロパティが削除された行為の定義

無限ループの魔法のメソッド属性避けてください:

super()を使用すると、特別なプロパティ、基底クラス呼び出し、__dict__割り当て

class Rectangle:
    def __init__(self,width=0,height=0):
        self.width = width
        self.height = height

    def __setattr__(self,name,value):
        if name == 'square':
            self.width = value
            self.height = value
        else:    #避免死循环的两种方式
           # super().__setattr__(name,value)
           self.__dict__[name] = value

    def getArea(self):
        return self.width * self.height

>>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100
>>>

記述子

別のクラスに割り当てられた属性の特定のクラスの型の例

__get__(self,instance,owner) プロパティへのアクセス、プロパティの戻り値
__set__(self,instance,value) プロパティの割り当ての呼び出しでは、何も返しません
__delete__(self,instance) コントロールの削除操作は、任意の値を返しません。
>>> class Mydecript:
    def __get__(self,instance,owner):
        print("getting...",self,instance,owner)
    def __set__(self,instance,value):
        print("setting...",self,instance,value)
    def __delete__(self,instance):
        print("deleting...",self,instance)

    
>>> class Test:
    x = Mydescript()

    
Traceback (most recent call last):
  File "", line 1, in 
    class Test:
  File "", line 2, in Test
    x = Mydescript()
NameError: name 'Mydescript' is not defined
>>> class Test:
    x = Mydecript()
#Mydecript是x的描述类
    
>>> test = Test()
>>> test.x
getting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050> 
>>> test.x = "X-man"
setting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050> X-man
>>> del test.x
deleting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050>

例:温度変換

class Celsius:
    def __init__(self,value = 26.0):
        self.value = float(value)

    def __get__(self,instance,owner):
        return self.value

    def __set__(self,instance,value):
        self.value = float(value)

class Fahrenheit:
    def __get__(self,instance,owner):
        return instance.cel * 1.8 + 32

    def __set__(self,instance,value):
        instance.cel = (float(value) - 32) / 1.8
        
class Temperature:
    cel = Celsius()
    fah = Fahrenheit()

    
>>> temp = Temperature()
>>> temp.cel
26.0
>>> temp.cel = 30
>>> temp.fah
86.0
>>> temp.fah = 100
>>> temp.cel
37.77777777777778
>>> 

6.カスタマイズされたシーケンス

詳細なPythonの魔法の方法

例:各要素のリスト内のレコードの不変、必要な数のカスタマイズされたリストの準備がアクセスされます

class CountList:
    def __init__(self,*args):
        self.values = [x for x in args]
        self.count = { }.fromkeys(range(len(self.values)),0)

    def __len__(self):
        return len(self.values)

    def __getitem__(self,key):
        self.count[key] += 1
        return self.values[key]

      
>>> c1 = CountList(1,3,5,7,9)
>>> c1[1]
3
>>> c2 = CountList(2,4,6,8,10)
>>> c2[1]
4
>>> c1[1]+c2[1]
7
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
>>> c2[1]
4
>>> c2.count
{0: 0, 1: 3, 2: 0, 3: 0, 4: 0}
>>> 

7.イテレータ

イテレータは達成することにある__next__()オブジェクトのメソッドをロールバックすることはできません

>>> string = "FishC"
>>> it = iter(string)
>>> next(it)
'F'
>>> next(it)
'i'
>>> next(it)
's'
>>> next(it)
'h'
>>> next(it)
'C'
>>> next(it)
Traceback (most recent call last):
  File "", line 1, in 
    next(it)
StopIteration
>>> string = "FishC"
>>> it = iter(string)
>>> while True:
    try:
        each = next(it)
    except StopIteration:
        break
    print(each)

    
F
i
s
h
C
>>> for each in string:
    print(each)

    
F
i
s
h
C
>>> 

例:フィボナッチ数を実装するイテレータを使用して

>>> class Fibs:
    def __init__(self,n=10):
        self.a = 0
        self.b = 1
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        self.a,self.b = self.b,self.a + self.b
        if self.a > self.n:
            raise StopIteration
        return self.a

    
>>> fibs = Fibs()
>>> for each in fibs:
    print(each)

    
1
1
2
3
5
8

おすすめ

転載: www.cnblogs.com/lelezuimei/p/11328687.html
おすすめ