Python study notes (seven) - Magic Method

1. The construction and destruction made

Magic methods is surrounded by a double underscore

__init__()method

__init__The method is not the default parameters, return value none. Examples of the class object initialization steps required to clear the override function

>>> 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__()method

__new__()The method returns an instance of an object when instantiating the object, the parameter is CLS, the first method is called

>>> 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__()method

__del__()The method is called when the object is about to be destroyed

>>> 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方法,我被调用了

After the object generation, all references to it have been del, will start the garbage collection mechanism

About garbage collection

2. arithmetic

Operators Magic corresponding method Chinese comments
+ __ add__(self, other) addition
- __ sub__(self, other) Subtraction
* __ mul__(self, other) multiplication
/ __ truediv__(self, other) True division
// __ floordiv__(self, other) Integer division
% __ mod__(self, other) Modulo division
divmod(a, b) __ divmod__(self, other) Divisor and the remainder the result of combined operations
** __ pow__(self, other[,modulo]) The self other than taking power again modulo
<< __ lshift__(self, other) Bitwise left shift
>> __ rshift__(self, other) Bitwise Right Shift
& __ and__(self, other) Bitwise AND operation
^ __ xor__(self, other) Bitwise XOR operation (the same is 0, 1 iso)
Shu __ or__(self, other) Bitwise OR operation (with a 1)

Inverse operation method of cube

>>> 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. Simple customization (timer)

time module

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秒'

Use perf_counter () and 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. property access

Magic Methods meaning
__ getattr__(self, name) When a user attempts to define the behavior of a non-existent property acquired during
__ getattribute__(self, name) When the definition of the class property is accessed behavior
__ setattr__(self, name, value) When an attribute is defined set of behavior
__ delattr__(self, value) Definition of when a property is deleted act

Avoid attribute magic method of infinite loop:

Using super () calls the base class, a special property __dict__assignment

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
>>>

The descriptor

Examples of the type of a particular class of attributes assigned to another class of

__get__(self,instance,owner) Access to property, the return value of the property
__set__(self,instance,value) In the Properties allocation call, do not return anything
__delete__(self,instance) Control delete operation does not return any value
>>> 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>

Example: temperature conversion

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. customized sequence

Detailed Python magic method

Example: preparation of a customized list of immutable, required number of records in the list for each element is accessed

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. iterator

Iterator is to achieve the __next__()object methods can not be rolled back

>>> 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
>>> 

Example: using an iterator implement Fibonacci number

>>> 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

Guess you like

Origin www.cnblogs.com/lelezuimei/p/11328687.html