面向对象

类:面向对象

  • 面向对象三大特性:继承 多态 封装

  • 类:

    • 每个实例化的对象都封装了类中相同的属性和方法,类是一个相似功能的结合体,
    • 对象:类名加()就是一个对象,类中的属性就是变量
  • 实例化:当执行类名加括号时就是实例化的过程

    • 实例:就是将对象赋值给变量

  • 面向对象编程,函数式编程,统称面向过程式编程

  • 面向过程式编程好处:

    • 优点:出色的完成你之前布置的所有需求

    • 缺点:但凡更改或者增加一条需求,可能整个项目都会随之改变

类的结构:

  • 类的调用:
  • class Student:  #构建学生类
        daily = '学习'            #变量在类中称为: 属性,静态属性 ,  静态字段 
        enamination = '考试'
    
        def work(self):           #函数在类中称为:方法,动态方法,   动态属性
            print('每天要上课')
    
        def homework(self):
            print('家庭作业')
    
    #类名的角度调用类中的属性:
    Student.cloth = "校服"                #增
    del Student.cloth                    #删
    Student.enamination = "不考试"        #改
    print(Student.enamination)           #查
    
    Student.work(44)  #工作中不使用       
    

  • self 方法传值:

  • #实例化对象时发生三件事:
    # 1.在内存中创建一个对象空间
    # 2.类名()自动执行__init__方法,并将这个对象空间(参数作为实参)传给self参数
    # 3.执行__init__方法里面的代码,给对象空间封装其属性
    
    #self 就是类中方法的第一个位置参数,
    #如果通过对象执行此方法,解释器就自动将此对象空间当做实参传给,self
    #约定俗称:类中的方法,第一个参数一般都设置成self
    
    class Student:                               #构建学生类,开启一个空间
        daily = '学习'                            #静态属性,类的属性
        enamination = '考试'
    
        def __init__(self,name,aex,hobby):       #双下方法  self接受的是obj实例化对象,封装属性
            self.name = name                     #name = '海洋'
            self.aex = aex
            self.hobby = hobby
    
        def work(self,color):                    #动态方法,类的方法
            self.color = color
            print(f"{self.name}每天要上课'")       #利用self对象空间,调用name属性
    
        def homework(self):
            print('家庭作业')
    
    # haiyang = Student('海洋',18,'台球')        #开辟一个haiyang空间,将参数传给self.name
    # junli   = Student('俊丽',18,'吃')
    # print(haiyang.__dict__)
    # print(junli.__dict__)
    
    #在任何地方都可以给对象封装属性
    haiyang = Student('海洋',18,'台球')         #haiyang对象 实例化,空间中存放着类指针
    haiyang.work("黑色")                        #可以在动态方法中添加属性
    print(haiyang.__dict__)
    
    #不可以在实例化里面修改静态属性
    # haiyang = Student('海洋',18,'台球')
    # haiyang.daily = "dada"   #不能修改,这样写没有修改类中的静态属性,而是在自己空间中添加
    # print(haiyang.daily)     #只能查看,不能修改类中的静态方法
    
    #obj = Student()           #实例化时开启一个空间,类名() 这是一个实例化过程,实例化一个对象
    # obj.age = '29'           #增
    # del obj.haha             #删
    # obj.sex = '女'            #改
    # print(obj.n)             #查看单个属性
    # print(obj.__dict__)      #查看全部属性,返回字典
    

  • 类添加属性和静态属性不可修改:

  • class A:
        address = "哒哒"
    
        def __init__(self,name):
            self.name = name
    
        def func(self):
            if self.name == 'aa':
                self.skins = "海洋"
    
        def func1(self):
            print(self.__dict__)
            A.aaa = "俊丽"
    
    #在外面封装属性
    # obj = A("aa")
    # respons = input("输入1进行修改")
    # if respons == "1":
    #     obj.dudu = "海洋"
    #在内部封装属性
    # obj = A("aa")
    # obj.func()
    # print(obj.__dict__)
    
    obj = A('aa')
    A.func1(obj)
    print(A.__dict__)
    
    def obj.address
    #单项不可逆
    #对象与对象之间互相独立
    #对象如果查询一个属性:对象空间---->类空间---->父类空间
    #类查询一个属性:类空间----->父类空间
    

  • 依赖关系:

  • #类与类之间,将一个类的类名或者对象传给另一个类的方法中(当实参传)
    class Elephant:  #大象类
        def __init__(self,name):
            self.name = name
    
        def open(self,ref1):
            print(f"大象{self.name}默念三声:开门")
            ref1.open_door()
    
        def close(self,ref1):
            print(f"大象{self.name}默念三声:关门")
            ref1.close_door()
    
    class Refrigerator:  #冰箱类
        def __init__(self,name):
            self.name = name
    
        def open_door(self):
            print(f'{self.name}冰箱门被打开了')
    
        def close_door(self):
            print(f'{self.name}冰箱门被关上了')
    
    haiyang = Elephant('海洋')
    ref = Refrigerator('海尔')
    haiyang.open(ref)
    haiyang.close(ref)
    

  • 组合关系:

  • #将一个类的对象封装成另一个类的对象的属性
    #一个类的方法只能有此类的对象去调用‘
    #一个类的方法的第一个self只接受此类的对象
    
    class Boy:
        def __init__(self,name):   		      #双下方法,自动执行,封装属性
            self.name = name
    
        def meet(self,girl_friend = None):
            self.girl_friend = girl_friend
    
        def have_diner(self):    		      #self = wu对象空间
            if self.girl_friend:
                print(f"{self.name}请{self.girl_friend.name}一起吃饭")
                self.girl_friend.co(self)     #等同于flower.co,将self传给co self
            else:
                print(f"一人吃饭")
    
    class Girl:
        def __init__(self,name,age):
            self.name = name
            self.age  = age
    
        def co(self,boy_friend):       #self = flower
            print(f"{boy_friend.name}和{self.name}一起溜达") 
    
    haiyang = Boy('海洋')
    flower = Girl('俊丽',18)
    
    haiyang.meet(flower)   		      #给meet传flower
    haiyang.have_diner()
    

  • 依赖和组合:

  • class Game():  # 英雄类
        def __init__(self, name, ad, hp):
            self.name = name
            self.ad = ad
            self.hp = hp
    
        def eauit_weapon(self, wea):  # wea == great_sword
            self.weapon = wea  # 组合:给盖伦这个对象封装了一个为wrapon属性
    
    
    class Weapon:  # 武器类
        def __init__(self, name, ad):
            self.name = name
            self.ad = ad
    
        def weapon_attack(self, p1, p2):
            p2.hp = p2.hp - self.ad
            print(f"{p1.name}利用{self.name}给了{p2.name}一下,{p2.name}还剩{p2.hp}滴血")
    
    
    gailun = Game('盖伦', 10, 100)  # 实例化人物
    jianhao = Game('赵信', 20, 90)
    
    great_sword = Weapon('大宝剑', 30)  # 实例化武器
    spear = Weapon('红缨枪', 40)
    
    gailun.eauit_weapon(great_sword)  # 依赖关系
    gailun.weapon.weapon_attack(gailun, jianhao)  # 给组合传参
    

继承:

  • 继承,子类继承父类的属性和方法,实现代码的重用,减少代码的编写

  • 继承:

    • 优点:

      • 节省代码,增强耦合性,代码规范
    • 缺点:

      • 类的耦合性继承要少用

      • 可读性差,拍错难,容易出现意料之外的错误

  • 单继承:

    • 子类以及对象可以调用父类的属性或者方法,不能增删改

    • 子类中如果有此属性,不找父类

    • super方法:用于调用父类
    • class Animal:
          live = "生命"
      
          def __init__(self,name,age,sex):
              self.name = name
              self.age = age
              self.sex = sex
      
          def eat(self):
              # print(self)
              print("动物吃饭")
      
      class Person(Animal):
      
          def __init__(self,name,age,sex,hobby):
              #方法1    #调用Animal的双下方法
              #Animal.__init__(self,name,age,sex)          
              #方法2    #super方法,可以不写(),默认(Person, self)
              super(Person, self).__init__(name,age,sex)  
              self.hobby = hobby
      
          def eat(self):
              print("人类吃法")
              super().eat()            #调用父类方法
      
      p1 = Person("海洋",18,'男','台球')
      print(p1.__dict__)
      p1.eat()                        #调用子类eat方法
      

  • 多继承:

    • python2.2之前:都是经典类,

    • python2.2至python2.7之间存在两种类型:经典类,新式类

    • python3 只有新式类 默认继承 class A(object)

    • 经典类:基类不继承object,

      • 遵循深度优先原则
      • 深入的规则是从左至右,从左边一直找到最底层,在从最底层一层一层往回找
    • 新式类:基类必须继承object

      • 遵循mro算法,mro依赖于c3算法

  • 多继承示例和算法:

    • class God:  #神仙
          def __init__(self,name):
              self.name = name
      
          def fly(self):
              print("会飞")
      
          def climb(self):
              print("神仙也要爬树")
      
      class Monkey:  #猴子
          def __init__(self,sex):
              self.sex = sex
      
          def climb(self):
              print('爬树')
      
      class Monkey_Sun(God,Monkey):   #悟空
          pass
      
      sun = Monkey_Sun
      
      print(Monkey_Sun.mro())        #mor查看多继承继承顺序!
      
    • super 多继承

    • #super(S,self) 严格按照,self从属于类的mro的执行顺序,执行类的下一位
      #示例1:
      class A:
          def f1(self):
              print("in A")
      
      class Foo(A):
          def f1(self):
              super(Foo,self).f1()  #FOO下一个类Bar
              print("in Foo")
      
      class Bar(A):
          def f1(self):
              print("in Bar")
      
      class Info(Foo,Bar):
          def f1(self):
              super(Info,self).f1()   #Info属于第一个类,每次找下一个类,下个是Foo
              print("in info f1")
      
      obj = Info()
      obj.f1()
      
      #示例2:
      class A:
          def f1(self):
              print("in A")
          
      class Foo(A):
          def f1(self):
              super(Foo,self).f1()
              print("in Foo")
      
      class Bar(A):
          def f1(self):
              print("in Bar")
      
      class Info(Foo,Bar):
          def f1(self):
              super(Foo,self).f1()
              print("in info f1")
      
      obj = Info()
      obj.f1()
      

    • MRO算法,C3算法:

    • class O:
          pass
      class D(O):
          pass
      class E(O):
          pass
      class F(O):
          pass
      class B(D,E):
          pass
      class C(E,F):
          pass
      class A(B,C):
          pass
      
      #取第一个表头匹配表尾,不相同取出,如果相同,匹配下一个列表的表头
      #例子[C,E,F,O] = 表头[C] 表尾[E,F,O]
      #只能拿表头匹配
      """
      mro(A) = mro(A(B,C))  原式
             = [A] + merge(mro(B),mro(C),[B,C])
             
      mro(B) = mro(B(D,E))
             = [B] + merge(mro(D),mro(E),[D,E])   #多继承
             = [B] + merge([D,O],[E,O],[D,E])     #单继承,O都是单继承
             = [B,D] + merge([O],[E,O],[E])       #取出D之后,删除D 
             = [B,D,E,O]
             
      mro(C) = mro(C(E,F))
             = [C] + merge(mro(E),mro(F),[E,F])
             = [C] + merge([E,O]),[F,O],[E,F]) 
             = [C,E] + merge([O]),[F,O],[F])
             = [C,E,F,O] 
             
      mro(A) = mro(A(B,C))   原式
             = [A] + merge([B,D,E,O],[C,E,F,O],[B,C])
             = [A,B] + merge([D,E,O],[C,E,F,O],[C])
             = [A,B,D] + merge([E,O],[C,E,F,O],[C])
             = [A,B,D,C] + merge([E,O],[E,F,O]) 
             = [A,B,D,C,E] + merge([O],[F,O]) 
             = [A,B,D,C,E,F,O]
      
      """
      

封装:

  • 将一些 数据属性和方法封装起来,还可以取出来,就是封装

  • 将你的数据放到列表里面也是封装,这是数据层面的

  • 常用的代码段放到函数里面,这是语句层面封装

  • 而类是一种更高级的封装,他可以将这两种封装在一起

  • 广义:

    • 把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用
  • 狭义:

    • 把属性和方法藏起来,外面不能调用,只能在类的内部调用

多态:

  • python:默认支持多态

    • 同一个对象,多种形态,A=1 A=“ad”
    • 一个类表现出多种形态,当你定义一个苹果支付类和微信支付类,他们同属于支付类,可以在支付类中定义双下方法属性

  • 鸭子类型:

    • python中 你看起来像鸭子,你就是鸭子
    • A,B两个类,没有任何关系,独立两个,但是里面的功能相似,所以python一般会将类似于A,B两个类里面的相似功能让其命名相同
    • A,B虽然无关系,但是很默契的制定了一个规范,让你使用更方便

类的约束:

  • 类的约束是一个开发规范,约束他的所有子类必须实现和他同名的方法,不同名抛出错误
  • 作用:
    • 在重要的逻辑,与用户数据相关等核心部分,我们要进行约束,避免此类错误

  • 第一种约束(常用):主动抛异常

  • #在父类中定义个pay方法,主动抛出异常,如果子类中没有定义pay方法,会寻找父类
    #即会报错,python推荐的一种约束方式
    
    class Payment:             #主动报错
        def pay(self,money):   #约定俗称,定义一种规范,子类要定义pay方法
            raise Exception('子类必须定义此方法')
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"利用支付宝支付了{money}")
    
    class Wechatpay(Payment):
        def fuqian(self,money):
            print(f"利用微信支付了{money}")
    
    #支付
    def pay(obj,money):
        obj.pay(money)
    
    obj1 = Alipay()       #调用支付宝支付
    pay(obj1,100)
    
    obj2 = Wechatpay()    #调用微信支付
    pay(obj2,200)
    
  • 第二种约束:实例化对象时报错,严谨

  • #利用抽象类的概念:基类如上设置,子类如果没有定义pay方法,在实例化对象时报错
    
    from abc import ABCMeta,abstractclassmethod
    
    class Payment(metaclass=ABCMeta):    #约束子类必须要有pay方法
        @abstractclassmethod
        def pay(self,money):
            pass
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"利用支付宝支付了{money}")
    
    class Wechatpay(Payment):
        def fuqian(self,money):
            print(f"利用微信支付了{money}")
    
    #支付
    def pay(obj,money):
        obj.pay(money)
    
    obj1 = Alipay()
    obj2 = Wechatpay()    #调用微信
    
    pay(obj1,100)
    pay(obj2,200)
    

反射:

  • 通过字符串形式,反射类中的属性和方法

  • 反射的四个函数:

  • hasattr(obj,"字符串")    #判断字符串是否存在类中
    getattr(obj,"字符串")    #进行反射调用字符串(属性或者方法)
    setattr(obj,"字符串")	  #添加属性
    delattr(obj,"字符串")    #删除属性
    

  • 实例角度反射:

  • class A:
        static_field = "静态属性"
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print("in A func")
    
    obj = A("海洋",18)
    
    if hasattr(obj,"static_field"):         #判断boj对象是否有static_field
        print(getattr(obj,"static_field"))   
    
    if hasattr(obj,"func"):                  #判断hasttr是否有函数
        getattr(obj,"func")()                #执行对象内的方法
    
    # print(getattr(obj,"name",None))  	     #没有属性,可以自定义设置返回值
    
    # setattr(obj,"hobby",'台球')       #* 添加一个属性
    # print(getattr(obj,"hobby"))
    #
    # delattr(obj,"hobby")             #*  删除一个属性
    # print(getattr(obj,"hobby"))
    

  • 类的角度反射:

  • class A:
        static_field = "静态属性"
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print(self)
            print(self.name)
            print("in A func")
    
    # print(hasattr(A,"static_field"))
    # print(getattr(A,"static_field"))
    obj = A("海洋",18)
    getattr(A,"func")(obj)
    

  • 脚本角度:

  • def func1():
        print("in func1")
    
    def func2():
        print("in func2")
    
    def func3():
        print("in func3")
    
    class B:
        static = "B类"
    
    import sys
    this_moudles = sys.modules[__name__]   #将__name__加入modules,获取当前脚本对象
    
    getattr(this_moudles,"func1")()      #调用函数
    
    cls = getattr(this_moudles,"B")      #获取到B,在进行实例化,调用
    obj = cls()
    print(obj.static)
    
    

  • 类的反射:

  • import sys
    
    class Auth:
        function_list = [("login","请登录"), ("register","请注册"),("exit","退出")]
    
        def login(self):
            print("登录函数")
    
        def register(self):
            print("注册函数")
    
        def exit(self):
            print("退出函数")
    
    while 1:
        obj = Auth()
        for num,option in enumerate(obj.function_list,1):
            print(num,option[1])
    
        func_name = int(input("请输入选择:").strip())
        if hasattr(obj,obj.function_list[func_name-1][0]):
            getattr(obj,obj.function_list[func_name-1][0])()
    

单例模式:

  • 一个类只能实例化一个对象,无论你实例化多少次,内存中都只有一个对象,节省内存

  • 主要是实例化对象,执行类中的方法

  • #单例模式:(面试必考)
    #一个类只能实例化一个对象,无论你实例化多少次,内存中都只有一个对象,节省内存
    #这个类的对象不是个性化的,主要是实例化对象之后去执行类中的方法
    
    class A:
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:          #如果为反的话
                obj1 = object.__new__(cls)  #调用object __new__方法封装类名
                cls.__instance = obj1       #object1对象
                return obj1
            else:
                return cls.__instance
    
    obj = A()
    obj1 = A()
    print(obj,obj1)
    
    #传参示例:
    class Baby:
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            if cls.__instance is None:
                cls.__instance = object.__new__(cls)   #object=super,找父类__new__   object类中的new可以创建空间  Baby = cls
            return cls.__instance
    
        def __init__(self,cloth,pants):  #self  = b1
            self.cloth = cloth
            self.pants = pants
    
    b1 = Baby('黑衣服','黑裤子')
    b2 = Baby('白衣服','白裤子')
    print(b1.__dict__)
    print(b2.__dict__)
    

类的成员:

  • 方法:

  • __ 将属性和方法变成私有

  • @classmethod : 调用类名

  • @staticmethod: 变成普通函数

  • @property : 将方法变成属性

  • 私有:

    • 私有静态属性,私有对象方法属性:
    • 类的外部都不可调用,只能在类中调用,适用于安全加密方式可以设置成私有(假私有)
  • #公有静态属性:
    class B:
        school_name = "海洋"
        __haha = "haha"
    
    class A(B):
        class_name = "python"
        __junli = "1"               #私有静态属性:外部不可访问
    
        def func(self):
            print(self.__junli)     #只能在类的内部可以访问
            print(self.__haha)
    
    obj = A()
    print(obj.func())
    
    #私有对象属性:
    class B:
        def __init__(self,weight):
            self.__weight = weight
    
    class A(B):
        def __init__(self,name,age,weight):
            super().__init__(weight)            #super要放在最上面
            self.name = name
            self.__age = age
    
        def func(self):
            print(self.__age)       #类的外部不能访问,只可以内部调用
            print(self.__weight)    #私有属性,父类中也不可调用
    
    obj = A("海洋",18,120)
    print(obj.func())
    
    #python中的所有私有成员:就是在私有成员前面加上_类名而已
    #不建议这样去访问
    class A:
        __junli = "1"
    print(A._A__junli)
    

@classmethod:调用类名

  • #定义一个学生类,统计学生个数
    class Student:
        sum = 0
        def __init__(self,name):
            self.name = name
            self.count()
    
        @classmethod                #类方法:由类名直接调用的方法,他会自动将类名传给cls
        def count(cls):
            cls.sum = cls.sum + 1   #使用类名是可以修改静态方法中的sum
    
        @classmethod
        def get_num(cls):
            return cls.sum
    
    haiyang = Student("海洋")
    junli = Student("俊丽")
    print(Student.get_num())     #类名调用
    

@staticmethod:变成普通函数

  • #静态方法:不依赖类,也不依赖于对象,他就是一个普通的函数
    #他就是一个普通的函数放置于类中结构更加清晰与合理
    class A:
    
        def func(self):
            print(111)
    
        @classmethod
        def a_func(cls):        #接受的是类名
            print(cls)
    
        @staticmethod
        def static_func(a):     #普通函数
            print(f"静态方法{a}")
    
    A.static_func(222)          #调用函数
    
    obj = A()			        #实例化调用也可以
    obj.static_func(222)
    
    

@property :将方法变成属性

  • #测试人体体脂
    #我们要让bmi方法,伪装成属性,虽然在代码级别没有什么提升,但是看起来更合理
    class Bmi:
        def __init__(self,name,weight,height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property   #将方法转为属性
        def bmi(self):
            return self.weight / self.height**2
    
    tb = Bmi("海洋",120,1.80)
    print(tb.bmi)               #调用属性
    
    
    #@property 方法变成属性,修改和删除不常用
    class Foo:
        def __init__(self,name):
            self.name = name
    
        @property
        def aaa(self):              #设置属性是名称要唯一,setter和deleter不能return
            print('get时候执行我')
    
        @aaa.setter
        def aaa(self,v):
            print(f"修改的时候执行我{v}")
    
        @aaa.deleter
        def aaa(self):
            print("删除时候执行我")
    obj = Foo("海洋")
    obj.aaa = "俊丽"        #调用被@aaa.setter装饰的函数,并且将"俊丽"传给v
    del obj.aaa            #删除
    
    print(obj.aaa)         #原属性aaa没有被修改
    

isinstance:判断对象与类的关系

  • class A:
        pass
    class B(A):
        pass
    class C(B):
        pass
    
    obj = B()
    print(isinstance(obj,B)) #前面是对象,判断OBJ是否是是由B类(B的派生类)实例化的对象
    print(isinstance(obj,A)) #
    print(isinstance(obj,C)) #
    

issubclass:

  • class A:     		    #父类,也叫基类
        pass
    class B(A):
        pass
    class C(B):
        pass
    
    print(issubclass(C,B))  #判断C是否是B的子类,子类也叫派生类
    print(issubclass(C,A))
    

Iterable:判断类可迭代和元类

  • from  collections import Iterable   #判断是否可迭代
    from  collections import Iterator   #判断迭代器
    
    s1 = "sadaada"          #class str(Iterable):
    # l1 = [1,2,3]
    # print(type(s1))       #判断对象从属于哪个类,一切皆对象
    # print(type(l1))
    
    print(isinstance(s1,Iterable))       #判断是否是可迭代对象,从继承角度
    
    #type 元类  python中一切皆对象,一个类也是一个对象
    #那么一个类肯定是由类实例化出来的
    #python中你创建的所有类,以及大部分str list等等,这些类都是从type元类实例化得来的
    
    # python中继承object都是新式类:
    # object也是有type元类实例化得来的
    #而type类还是object子类,这种关系比较神奇无法使用python代码表述
    

types:

  • #函数与方法区别
    #函数:全都是显性传参
    #方法:存在隐性传参     #java里面就是有方法,c++中都是函数
    
    from  types import  FunctionType  #判断函数
    from types import MethodType      #判断方法
    
    def func():
        pass
    
    class A:
        def func(self):
            pass
        @staticmethod
        def f(self):
            pass
    
    print(isinstance(func,FunctionType))      #判断是否是函数
    print(isinstance(func,MethodType))
    
    print(isinstance(A.func,FunctionType))    #类名调用func 是一个函数
    print(isinstance(A.func,MethodType))
    
    obj = A()
    print(isinstance(obj.func,FunctionType))
    print(isinstance(obj.func,MethodType))    #通过对象调用是方法
    
    obj = A()
    print(isinstance(obj.f,FunctionType))     #通过对象调用静态方法是函数
    print(isinstance(obj.f,MethodType))
    

双下方法:

  • 双下方法触发条件:

    • __new__:  在实例化时候触发,触发优先级比__init__高,单例模式使用
      __len__:  len(obj)  len对象时候触发
      __str__:  str(obj)或者格式化输入时候触发
      __call__: 实例化对象后触发,call优先级比__init__方法低
      

  • __new__方法:

  • #开辟一个空间
    class A:
        def __init__(self):
            print("in init")
    
        def __new__(cls, *args, **kwargs):  #cls = A类名
            print("in new")
            object1 = object.__new__(cls)   #2.利用object类的new产生一个空间
            return object1                 #3.将这个对象空间返回给A()
    
    obj = A()                              #1.先触发__new__并且将类名自动传给cls
    

  • __len__方法:

  • #一个对象值所以可以使用len函数,是这个对象从属于类中有__len__方法
    class A:
        def __init__(self,name,age,hobby):
            self.name = name
            self.age = age
            self.hobby = hobby
    
        def __len__(self):
            print("执行了__len__方法")
            return len(self.__dict__)
    
    obj = A("海洋",18,"台球")
    ret = len(obj)             #触发A类中的__len__方法,ret返回10
    print(ret)
    
  • __str__方法:

  • class Student:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __str__(self):
            return  f"{self.name}{self.age}{self.sex}"  #str优先级高
    
        # def __repr__(self):   #跟str双下方法一样
        #     return  f"{self.name}{self.age}{self.sex}"
    
    obj = Student("海洋",18,"男")
    obj1 = Student("俊丽",18,"女")
    # # print(str(obj))  #会触发
    # print(obj)    #打印一个实例就会触发__str__
    # print(obj1)
    print(f"此对象为{obj}") #格式化输出也会触发
    
  • __call__方法:

  • # 对象call ,类加()触发
    class A:
        def __init__(self):
            self.a = 1
            print(111)
    
        def __call__(self, *args, **kwargs):
            print(222)
    
    obj = A()   #实例化触发
    obj()
    
  • __enter__和__exit__方法:

  • #对一个对象类似于进行with语句上下文管理,必须要在类当中定义__enter__和__exit__
    class A:
        def __init__(self,text):
            self.text = text
    
        def __enter__(self):
            self.text = self.text + "您来了"  #1
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.text = self.text + "这就走了"  #
    
    with A("大爷") as f1:  #2
        print(f1.text)
    print(f1.text)  #4
    

  • #__eq__    对象比较是触发
    #__del__   析构方法,手动垃圾挥手
    #__item__  对一个对象,执行字典的操作,执行item
    #__iter__  将一个对象设置成一个可迭代对象,for循环取值或者list
    

异常处理:

  • 一旦程序出现异常,异常处理会及时捕捉你的错误,不至于使你的程序崩溃

  • 异常处理不能经常使用:耗费性能,有些错误是需要分流使用的,代码的可读性变差

  • 关键的节点时候使用

  • 单分支:

  • try:
        l1 = [1,2,3,4,5]
        print(l1[6])
    
    except IndexError as e:   #当索引报错后,后面的就不会再走了
        print("索引错误")
    
    print(111)
    

  • 多分支和分流:

  • try:
        l1 = [1,2,3,4,5]
        print(l1[6])
    
        dic = {1:2,'a':'b'}
        print(dic[3])
    
        num = input("请输入序号:")
        int(num)
    
    except IndexError as e:   #当索引报错后,后面的就不会再走了
        print("索引错误")
    except KeyError as e:   
        print('没有此键')
    except ValueError as e:
        print("转化错误")
    print(111)
    
    #程序分流
    dic = {
        1:666,
        2:333,
        3:555
    }
    
    while 1:
        try:
            num = input("请输入序号:")
            int(num)
            print(dic[int(num)])
    
        except KeyError as e:  					 
            print(f'选项超出范围,请重新输入{e}')    #e是将错误打印出来
        except ValueError as e:
            print(f"请输入数字{e}")
    

  • 万能异常:

  • # 万能异常
    # 什么时候使用万能异常,什么时候使用多分支?
    # 如果你只是想把整个异常全部处理掉,让程序继续执行,就用万能异常
    # 如果出现了异常,你是想根据不同的异常执行不同的逻辑流程,你要采取多分支
    
    dic = {
        1:666,
        2:333,
        3:555
    }
    
    try:
        num = input("请输入序号:")
        int(num)
        print(dic[int(num)])
    
    except Exception as e:   #代表所有错误,全部捕获
        print(e)
    print(111)
    
    

  • 万能异常加分流:

  • dic = {
        1:666,
        2:333,
        3:555
    }
    while 1:
        try:
            num = input("请输入序号:")
            int(num)
            print(dic[int(num)])
    
        except KeyError as e:
            print('选项超出范围,请重新输入')
        except ValueError as e:
            print("请输入数字")
        except Exception:       	#以上异常没有pass掉
            pass
    
    

  • 异常处理其他成员:无异常时候执行

  • dic = {
        1:666,
        2:333,
        3:555
    }
    try:
        num = input("请输入序号:")
        int(num)
        print(dic[int(num)])
    
    except KeyError as  e:
        print("选项超出范围,重新输入")
    except Exception:
        pass
    else:         					 #以上无异常执行else语句,否则不执行else语句
        print(666)
    
    

  • finally:在出现错误前执行此语句

  • #使用场景,文件读写,数据库连接
    try:
        int("a")
    finally:                #finally:  在出错误前执行此语句
        print(777)
    
    def func():             #函数结束前执行finally
        try:
            a = 1
            b = 2
            return  a + b
        finally:
            print(666)
    print(func())
    

  • raise/assert:主动抛出异常

  • raise Exception("主动抛出异常")
    
    assert          #断言:可以添加条件加判断
    assert  1 == 2
    print(11)
    

  • 自定义异常(了解)

  • class Connection(BaseException):
        def __init__(self,msg):
            self.msg=msg
    
    raise Connection("触发了连接异常")
    
posted @ 2019-07-09 15:40  海洋1994  阅读(194)  评论(0编辑  收藏  举报