python——day_10:魔法方法


title: ‘python——day_10:魔法方法’
date: 2019-11-05 20:08:56
categories:

  • python基础
    tags:
  • python基础

python——day_10:魔法方法

构造和析构

  • 魔法方法总是被双下划线包围

  • 魔法方法是面向对象的python的一切

    # 为什么类中有时候有__init__?因为需求
    class Rectangle:
        def __init__(self,x,y):
            self.x = x
            # 这里是可以理解为 self.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()
    

魔法方法

  • __init__函数没有返回值:

    class A:
        def __init__(self):
            return "1"
    a = A()#不要给init做返回
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-3-8592369aa820> in <module>
          2     def __init__(self):
          3         return "1"
    ----> 4 a = A()
    
    TypeError: __init__() should return None, not 'str'
    
  • new(cls[…])第一个被调用的方法,返回cls的对象

    # __new__(cls[....])第一个被调用的方法,返回cls的对象
    class CapStr(str):
        def __new__(cls,string):
            string = string.upper()#变成大写后字符串
            return str.__new__(cls,string)
    a = CapStr("I love FishC.com")
    a#解释是因为重写了str的方法,所以这里返回的就是默认转换为大写
    'I LOVE FISHC.COM'
    
  • del(self)当对象销毁的时候,自动调用,垃圾回收机制自动销毁

    #__del__(self)当对象销毁的时候,自动调用,垃圾回收机制自动销毁
    class C:
        def __init__(self):
            print("我是__init__方法,我被调用了")
        def __del__(self):
            print("我是del方法")
    c1 = C()
    我是__init__方法,我被调用了
    
  • 类似于type也是一个__init__方法

    type(len)
    builtin_function_or_method
    type(int)
    type
    class C:
        pass
    type(C)#工厂函数就是类对象
    
  • __add__方法:

    #这里贴图片
    class New_int(int):
        def __add__(self,other):
            return int.__sub__(self,other)
    a = New_int(1)
    b = New_int(3)
    a+b
    -2
    
    

    错误实例:无限递归

    #自己重写
    class Try_int(int):
        def __add__(self,other):
            return self+other
    a = Try_int(1)
    b = Try_int(3)
    a+b# 先调用a的add方法,self就是a,others是b,然后+又来,然后递归了
    #无限递归了
    
  • 反运算操作符

    # 反运算操作符
    class Nint(int):
        def __radd__(self,other):
            return int.__sub__(self,other)
    1+b
    # 反运算操作符
    class Nint(int):
        def __rsub__(self,other):
            return int.__sub__(self,other)
    a = Nint(5)
    3 - a
    

简单定制(定时器)

import time as t
class MyTimer():
    def __init__(self):
        self.prompt = "未开始计时"
        self.unit= ['年','月','日','时','分','秒']
        self.lasted = []
#         self.start = 0# 属性覆盖方法
        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.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]
        print(self.prompt)
        #为下一轮计时进行初始化
        self.begin = 0
        self.end = 0
t1 = MyTimer()

属性访问:

  • 举个简单例子:

    class C:
        def __init__(self):
            self.x = 'x-man'
    c = C()
    c.x
    
  • 对属性访问抽象方法的解释:

    class C:
        def __getattribute__(self,name):#定义当该类的属性被访问时候的行为
            print("getattribute")
            return super().__getattribute__(name)
        def __getattr__(self,name):#定义当用户试图获取一个不存在的属性时的行为
            print("getattr")
        def __setattr__(self,name,value):# 当一个属性被设置的行为
            print("setattr")
            super().__setattr__(name,value)
        def __delattr__(self,name):# 定义当一个属性被删除时候的行为
            print("delattr")
            super().__delattr__(name)
    c = C()
    c.x
    # 
    
  • 错误实例:

    #实例
    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:
                self.name = value
        def getarea(self):
            return self.width *self.height
    r1 = Rectangle(4,5)
    #报错原因时 init函数,然后递归调用自身
    
  • 修改上面代码:

    #修改
    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)
        def getarea(self):
            return self.width *self.height
    r1 = Rectangle(4,5)
    

描述符

  • 描述符就是将某种特殊属性的类的实例指派给另一个类的属性

  • get(self,instance,owner)
    用于访问属性,它返回属性的

  • set(self,instance,value)
    将在属性分配操作中调用,不返回任何内容

  • delete(self,instance)
    控制删除操作,不返回任何内容

  • 实例1:

    class MyDecriptor:
        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("delete...",self,instance)
    class Test:
        x = MyDecriptor()
    test = Test()
    test.x
    getting.. <__main__.MyDecriptor object at 0x0000014CBBF3BD30> <__main__.Test object at 0x0000014CBB9A8898> <class '__main__.Test'>
    
  • 实例2:

    class MyProperty:
        def __init__(self,fget=None,fset = None,fdel = None):
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
        def __get__(self,instance,owner):
            return self.fget(instance)
        def __set__(self,instance,value):
            self.fset(instance,value)
        def __delete__(self,instance):
            self.fdel(instance)
    class C:
        def __init__(self):
            self._x = None
        def getX(self):
            return self._x
        def setX(self,value):
            self._x = value
        def delX(self):
            del self._x
        x = MyProperty(getX,setX,delX)
    c = C()
    c.x = 1
    c.x
    1
    
  • 实例三:

    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
    temp.cel = 30
    temp.fah
    

容器定制

  • 容器类型的协议
  1. 如果说定制容器不可变的话,只需要定义__len__和__getitem__方法
  2. 如果定制容器可变的话,不仅需要上面方法,还需要多定义__setitem__和__delitem__
  • 实例:

    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]
    
    

迭代器

  • for i in "fishc":
        print(i)
    
    
  • links = {"小甲鱼":"采购","鱼":'金鱼'}
    for each in links:
        print("%s->%s"%(each,links[each]))
    
    
  • it = iter(string)
    while True:
        try:
            each = next(it)
        except StopIteration:
            break
        print(each)
    
    
  • 迭代器魔法方法

    # 迭代器魔法方法 __iter__() __next__()
    class Fibs:
        def __init__(self):
            self.a = 0
            self.b = 1
        def __iter__(self):
            return self
        def __next__(self):
            self.a,self.b = self.b,self.a+self.b
            return self.a
    fibs = Fibs()
    for each in fibs:
        if each < 20:
            print(each)
    
    

生成器

  • # 生成器:
    a = [i for i in range(100) if not(i%2) and i % 3]
    
    
  • c = {i for  i in [1,1,2,3,5]}
    
    

你可能感兴趣的:(python,学生)