python面向对象的内置函数和异常

内置函数

str

  __str__方法会在对象被打印时自动触发,print功能打印的就是它的返回值,
    我们通常基于方法来定制对象的打印信息,该方法必须返回字符串类型
    class People:
      def __init__(self,name,age):
        self.name=name
        self.age=age
      def __str__(self):
        return '<Name:%s Age:%s>' %(self.name,self.age) #返回类型必须是字符串
    p=People('lili',18)
    print(p) #触发p.__str__(),拿到返回值后进行打印
    # <Name:lili Age:18>

del

  __del__会在对象被删除时自动触发。由于Python自带的垃圾回收机制会自动清理Python程序的资源,
    所以当一个对象只占用应用程序级资源时,完全没必要为对象定制__del__方法,
      但在产生一个对象的同时涉及到申请系统资源(比如系统打开的文件、网络连接等)的情况下,关于系统资源的回收,
        Python的垃圾回收机制便派不上用场了,需要我们为对象定制该方法,用来在对象被删除时自动触发回收系统资源的操作
          class Student():
              def __init__(self, name, age):
                  self.name = name
                  self.age = age
                  self.f = open('a', mode='r')

              # 1. 手动删除对象执行
              # 2. 应该程序执行完毕自动触发
              def __del__(self):
                  print("__del__")
                  self.f.close()

          obj = Student('ly', 19)
          # del obj
          print("end----->")

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

    class Foo(object):
      pass 
    obj = Foo()  
    isinstance(obj, Foo)

issubclass(sub, super)检查sub类是否是 super 类的派生类

    class Foo(object):
        pass

    class Bar(Foo):
        pass

    issubclass(Bar, Foo)

setattr,delattr,getattr

  class Foo:
      x=1
      def __init__(self,y):
          self.y=y

      def __getattr__(self, item):
          print('----> from getattr:你找的属性不存在')


      def __setattr__(self, key, value):
          print('----> from setattr')
          # self.key=value #这就无限递归了,你好好想想
          # self.__dict__[key]=value #应该使用它

      def __delattr__(self, item):
          print('----> from delattr')
          # del self.item #无限递归了
          self.__dict__.pop(item)

  #__setattr__添加/修改属性会触发它的执行
  f1=Foo(10)
  print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
  f1.z=3
  print(f1.__dict__)

getattribute:不管存不存在我都运行

  class Foo:
      def __init__(self,x):
          self.x=x

      def __getattribute__(self, item):
          print('不管是否存在,我都会执行')

  f1=Foo(10)
  f1.x
  f1.xxxxxx

setitem,__getitem,delitem

class Foo:
    def __init__(self,name):
        self.name=name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__) 

call:对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print('__call__')


obj = Foo() # 执行 __init__
obj()       # 执行 __call__

异常

1、什么是异常

异常是程序发生错误的信号。程序一旦出现错误,便会产生一个异常,
  若程序中没有处理它,就会抛出该异常,程序的运行也随之终止

2、异常的分类:

错误分成两种,
  一种是语法上的错误SyntaxError,这种错误应该在程序运行前就修改正确:
      如:print(111   后面的括号不加就是一个语法错误SyntaxError
  另一种就是逻辑错误,常见的逻辑错误如:
      # TypeError:数字类型无法与字符串类型相加
          1+’2’

      # ValueError:当字符串包含有非数字的值时,无法转成int类型
          num=input(">>: ") #输入hello
          int(num)

      # NameError:引用了一个不存在的名字x
          x

      # IndexError:索引超出列表的限制
          l=['egon','aa']
          l[3]

      # KeyError:引用了一个不存在的key
          dic={'name':'egon'}
          dic['age']

      # AttributeError:引用的属性不存在
          class Foo:
              pass
          Foo.x

      # ZeroDivisionError:除数不能为0
          1/0

3、异常处理

分别有下面几种处理形式:
  1.为了保证程序的容错性与可靠性,即在遇到错误时有相应的处理机制不会任由程序崩溃掉,我们需要对异常进行处理,处理的基本形式为

            try:
                被检测的代码块
            except 异常类型:
                检测到异常,就执行这个位置的逻辑  
  2.如果我们想分别用不同的逻辑处理,需要用到多分支的except(类似于多分支的elif,从上到下依次匹配,匹配成功一次便不再匹配其他)

            try:
                被检测的代码块
            except NameError:
                触发NameError时对应的处理逻辑
            except IndexError:
                触发IndexError时对应的处理逻辑
            except KeyError:
                触发KeyError时对应的处理逻辑 
  3.如果我们想多种类型的异常统一用一种逻辑处理,可以将多个异常放到一个元组内,用一个except匹配

            try:
                被检测的代码块
            except (NameError,IndexError,TypeError):
                触发NameError或IndexError或TypeError时对应的处理逻辑
  4.如果我们想捕获所有异常并用一种逻辑处理,Python提供了一个万能异常类型Exception

            try:
                被检测的代码块
            except NameError:
                触发NameError时对应的处理逻辑
            except IndexError:
                触发IndexError时对应的处理逻辑
            except Exception:
                其他类型的异常统一用此处的逻辑处理
  5.在多分支except之后还可以跟一个else(else必须跟在except之后,不能单独存在),
      只有在被检测的代码块没有触发任何异常的情况下才会执行else的子代码块
            try:
                被检测的代码块
            except 异常类型1:
                pass
            except 异常类型2:
                pass
            ......
            else:
                没有异常发生时执行的代码块

4、何时使用异常处理

1.如果错误发生的条件是“可预知的”,我们应该用if来进行”预防”,如下

    age=input('input your age>>: ').strip()
    if age.isdigit(): # 可预知只有满足字符串age是数字的条件,int(age)才不会触发异常,
        age=int(age)
    else:
        print('You must enter the number')
2.如果错误发生的条件“不可预知”,即异常一定会触发,
  那么我们才应该使用try...except语句来处理。
posted @ 2021-07-15 17:28  zhutianyu  阅读(51)  评论(0)    收藏  举报