python中面向对象的3大特性,类内置函数和方法,异常处理

面向对象

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

继承与派生

什么是继承
继承是一种新建类的方式,新建的类称为子类,子类会遗传父类的属性,可以减少代码冗余,
在python中,子类(派生类)可以继承一个或者多个父类(基类,超类)
继承与抽象
继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承
继承与重用性
通过继承的方式新建类B,让B继承A,B会遗传A的所有属性(数据属性和函数属性),实现代码重用

SubClass.__bases__ #__bases__查看所有继承的父类

例如:

class Parent1:
    pass
class Parent2(object):
    pass
class Sub1(Parent1):
    pass
class Sub2(Parent1,Parent2):
    pass

print(Sub1.__bases__)    #查看类的父类
print(Sub2.__bases__)

print(Parent1.__bases__)  #在python3新建的类,默认都有一个父类(object)  #在python2中,默认是没有父类,可以添加(object)为父类
print(Parent2.__bases__)
派生
子类也可以添加自己新的属性或者重新定义属性,如果子类重新定义了自己的属性且与父类重名,在调用新增的属性的时候就以自己的为准
python中类的分类

在python2中:
1、经典类,指的就是没有继承object类的类,以及该类的子类
2、新式类,指的就是继承object类的类,以及该类的子类
在python3中:
统一都是新式类
例如:

class OldboyPeople:
    school='oldboy'

    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))
class OldboyStudent(OldboyPeople):
    def learn(self):
        print('%s is learning' %self.name)
    def tell_info(self):
        print('我是学生:',end='')
class OldboyTreacher(OldboyPeople):
    def teach(self):
        print('%s is teaching' %self.name)
    def tell_info(self):
        print('我是老师:',end='')
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))
stu1=OldboyStudent('lqx','19','male')
teaching=OldboyTreacher('egon','23','female')

print(stu1.__dict__)
print(stu1.school)
# print(stu1.x)  #查找顺序,对象->子类->父类 没有就抛异常
print(teaching.__dict__)

# 如果子类有这个函数,就不会去父类去找
stu1.tell_info()
teaching.tell_info()

#属性查找:
class Foo:
    def f1(self):
        print('foo.f1')
    def f2(self):       #self应该为Bar初始化的obj对象
        print('foo.f2')
        self.f1()   #Bar初始化的obj.f1()
class Bar(Foo):
    def f1(self):
        print('bar.f1')
obj=Bar()
print(obj.__dict__)
obj.f2()  #先在bar类中查找,如果没有就会去父类查找,

# >>>foo.f2
# bar.f1
子类重用父类的方法
指名道姓的使用
#子类指名道姓使用父类属性
#实现学生还有课程、学号
class OldboyPeople:
    school='oldboy'

    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s 课程:%s 学号:%s>' %(self.name,self.age,self.sex,self.coutse,self.stu_id))
class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,coutse,stu_id):
        OldboyPeople.__init__(self,name,age,sex)   #子类指名道姓使用父类属性
        self.coutse=coutse
        self.stu_id=stu_id
    def learn(self):
        print('%s is learning' %self.name)
    def tell_info(self):
        print('我是学生:',end='')
        OldboyPeople.tell_info(self)    #子类指名道姓使用父类属性


stu1=OldboyStudent('lqx','19','male','python','123')
stu1.tell_info()
使用super来调用父类的方法

1、之前使用指名道姓的引用另一个类,或者父类的方法。
2、现在使用super(本类名.self).方法 的方式调用父类的方法
3、这种方法只能调用父类的方法

class OldboyPeople:
    school = 'Oldboy'
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,course):
        # OldboyPeople.__init__(self,name,age,sex)
        super(OldboyStudent,self).__init__(name,age,sex)
        self.course=course

    def tell_info(self):
        print('我是学生: ',end='')
        # OldboyPeople.tell_info(self)
        super(OldboyStudent,self).tell_info()

stu1=OldboyStudent('lqx','12','male','python')
print(stu1.name,stu1.age,stu1.sex,stu1.course)
stu1.tell_info()
super方法
class Foo:
    # def f2(self):
        # print('>>>>2')
    def f1(self):
        print('foo.f1')
        Foo.f2(123)
class Bar:
    def f2(self):
        print('bar f2')
class Sub(Bar,Foo):
    pass

s=Sub()
print(Sub.mro())  #[<class '__main__.Sub'>, <class '__main__.Bar'>, <class '__main__.Foo'>, <class 'object'>]

s.f1()  #说明严格按照mro()中的查找顺序来查找

#查找顺序,Sub->Bar->Foo
组合的使用

软件重用的重要方式除了继承之外还有另外一种方式,即:组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称之为类的组合

#学生有年龄名字,性别,学号,还有生日,使用组合添加出生日
#组合区别于继承,什么有什么的一种关系
class OldboyPeople:
    school='oldboy'

    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s 课程:%s 学号:%s>' %(self.name,self.age,self.sex,self.coutse,self.stu_id))
class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,coutse,stu_id,date_obj):
        OldboyPeople.__init__(self,name,age,sex)
        self.coutse=coutse
        self.stu_id=stu_id
        self.birth=date_obj   #3、把date_obj添加到self这个对象中

    def learn(self):
        print('%s is learning' %self.name)
    def tell_info(self):
        print('我是学生:',end='')
        OldboyPeople.tell_info(self)

class OldboyTreacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        OldboyPeople.__init__(self, name, age, sex)
        self.level = level
        self.salary = salary
    def teach(self):
        print('%s is teaching' %self.name)
    def tell_info(self):
        print('我是老师:',end='')
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

class Date:
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day

    def tell_birth(self):
        print('出生日期是:%s-%s-%s' % (self.year, self.mon, self.day))

date_obj=Date('1921',21,23)   #1、先初始化生日得到一个对象
stu1=OldboyStudent('lqx','19','male','python','12',date_obj)  #2、初始化学生类,把初始化生日的对象带入一起初始化
stu1.birth.tell_birth()   #4、就可以调用对象stu1中birth的属性

teacher1=OldboyTreacher('www','123','female',10,12)
date_obj2=Date(1990,2,18)
teacher1.brith=date_obj2


# 添加一个生日,把生日任何人都有生日,把生日放到父类中,初始化的时候就会有生日
class OldboyPeople:
    school='oldboy'

    def __init__(self,name,age,sex,date_obj):
        self.name=name
        self.age=age
        self.sex=sex
        self.birth=date_obj
    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s >' %(self.name,self.age,self.sex))

class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,coutse,stu_id,date_obj):
        OldboyPeople.__init__(self,name,age,sex,date_obj)
        self.coutse=coutse
        self.stu_id=stu_id


    def learn(self):
        print('%s is learning' %self.name)
    def tell_info(self):
        print('我是学生:',end='')
        OldboyPeople.tell_info(self)
        print('课程:%s 学号:%s' %(self.coutse,self.stu_id))

class OldboyTreacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary,date_obj):
        OldboyPeople.__init__(self, name, age, sex,date_obj)
        self.level = level
        self.salary = salary
    def teach(self):
        print('%s is teaching' %self.name)
    def tell_info(self):
        print('我是老师:',end='')
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

class Date:
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day
    def tell_birth(self):
        print('出生日期是:%s-%s-%s' % (self.year, self.mon, self.day))

class OldboySale(OldboyPeople):
    def __init__(self,name,age,sex,kpi,date_obj):
        OldboyPeople.__init__(self,name,age,sex,date_obj)
        self.kpi=kpi

    def tell_info(self):
        print('销售:%s',end='')
        OldboyPeople.tell_info(self)

date_obj=Date('1921',21,23)   
stu1=OldboyStudent('lqx','19','male','python','12',date_obj)  
stu1.birth.tell_birth()  

date_obj2=Date(1990,2,18)
teacher1=OldboyTreacher('www','123','female',10,12,date_obj2)
teacher1.birth.tell_birth()
print(teacher1.__dict__)

date_obj1=Date(1800,12,32)
sale1=OldboySale('mmp','12','female',7.1,date_obj1)
print(sale1.__dict__)
sale1.birth.tell_birth()



#学生选课,添加选择的课程,在初始化的时候初始化一个属性为list
class OldboyPeople:
    school='oldboy'

    def __init__(self,name,age,sex,date_obj):
        self.name=name
        self.age=age
        self.sex=sex
        self.birth=date_obj
    def tell_info(self):
        print('<名字:%s 年龄:%s 性别:%s >' %(self.name,self.age,self.sex),end='')

class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,date_obj,stu_id):
        OldboyPeople.__init__(self,name,age,sex,date_obj)
        self.coutse=[]
        self.stu_id=stu_id


    def learn(self):
        print('%s is learning' %self.name)
    def tell_info(self):
        print('我是学生:',end='')
        OldboyPeople.tell_info(self)
        print('学号:%s' %self.stu_id)

class OldboyTreacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary,date_obj):
        OldboyPeople.__init__(self, name, age, sex,date_obj)
        self.level = level
        self.salary = salary
        self.courses=[]
    def teach(self):
        print('%s is teaching' %self.name)
    def tell_info(self):
        print('我是老师:',end='')
        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

class Date:
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day
    def tell_birth(self):
        print('出生日期是:%s-%s-%s' % (self.year, self.mon, self.day))

class OldboySale(OldboyPeople):
    def __init__(self,name,age,sex,kpi,date_obj):
        OldboyPeople.__init__(self,name,age,sex,date_obj)
        self.kpi=kpi

    def tell_info(self):
        print('销售:%s',end='')
        OldboyPeople.tell_info(self)


class Course:
    def __init__(self,name,price,period):
        self.name=name
        self.price=price
        self.period=period
    def tell_info(self):
        print('课程详细信息:(%s,%s,%s)' %(self.name,self.price,self.period))

Python=Course('python自动化',4000,'3mon')
Linux=Course('linux学习',2000,'3mon')

# date_obj=Date(1990,12,32)
# tearch1=OldboyTreacher('egon','19','male',100,3000,date_obj)
# tearch1.courses.append(Python)
# for course in tearch1.courses:
#     course.tell_info()

date_obj=Date(1994,21,12)
stu1=OldboyStudent('LQX',29,'male',date_obj,'1')
stu1.coutse.append(Linux)
stu1.coutse.append(Python)
stu1.tell_info()
for coutse in stu1.coutse:
    coutse.tell_info()
抽象类

主要使用abc模块,实现归一化,父类有的方法,子类必须有
需要在父类的方法头部加上@abc.abstractclassmethod

例如:

import abc
class File(metaclass=abc.ABCMeta):
    @abc.abstractmethod 
    def read(self):   #必须要定义下面的方法,如果没有就不让实例化
        pass
    @abc.abstractmethod
    def write(self):
        pass
class Sata(File):
    def read(self):
        pass
    def write(self):
        pass
    def asb(self):
        print('adsf')
Fil=Sata()
Fil.asb()
print(Sata.mro())
继承的实现原理

1、继承顺序:
经典类:当类是经典类时,多继承情况下,在要查找属性不存在时,会按照深度优先的方式查找下去
新式类:当类是新式类时,多继承情况下,在要查询属性不存在时,会按照广度优先的方式查找下去
2、使用属性来查看继承的顺序:
print(类名.mro())

class A(object):
    # def test(self):
    #     print('from A')
    pass

class B(A):
    # def test(self):
    #     print('from B')
    pass

class C(A):
    # def test(self):
    #     print('from C')
    pass
class D(B):
    # def test(self):
    #     print('from D')
    pass

class E(C):
    # def test(self):
    #     print('from E')
    pass
class F(D,E):
    # def test(self):
    #     print('from F')
    pass

f1=F()
print(F.mro())

多态与多态性

多态
同一种事物的多种形态
# import abc
# class Animal(metaclass=abc.ABCMeta):
#     @abc.abstractclassmethod
#     def speak(self):
#         pass
class Pig:
    def speak(self):
        print('heng')
class Dog:
    def speak(self):
        print('wang')
class People:
    def speak(self):
        print('say')
class Radio:
    def speak(self):
        print('radio say')
people1=People()
dog1=Dog()
pig1=Pig()
多态性
指的是在不考虑对象具体类型的情况下,直接使用对象(对象的方法),就是力求一个事物定义一个类
import abc   
class Animal(metaclass=abc.ABCMeta):   #规定子类必须要有父类的方法
    def speak(self):
        pass
class Pig(Animal):
    def speak(self):
        print('heng')
class Dog(Animal):
    def speak(self):
        print('wang')
class People(Animal):
    def speak(self):
        print('say hello')
    def talker(self):
        print('talker')
people1=People()
dog1=Dog()
pig1=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
# people1.speak()
# dog1.speak()
# pig1.speak()
people1.talker()
#写一个函数,直接传值,就可以实现其功能,定义一个统一的接口
def speak(obj):
    obj.speak()
speak(people1)
speak(dog1)
speak(pig1)

Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下

#str,list,tuple都是序列类型:
s=str('hello')
l=list([1,2,3,4])
t=tuple((1,2,3,4))
#我们可以在不考虑三者的类型的前提下使用,s,l,t
s.__len__()
l.__len__()
t.__len__()

len(s)
len(l)
len(t)

封装

封装之如何隐藏

1、__开头的属性只是一种语法意义上的变形,并不会真的限制外部的访问
2、这种变形只在类定义阶段发送一次,类定义之后在新增的__开头的属性不会变形
3、这种隐藏只对外,不对内,因为类内部定义的属性在定义类的阶段统一发生变形

class Foo:
    __n=1   #隐藏后外部调用变成_Foo__n=1
    def __init__(self,x,y):
        self.__x=x
        self.y=y
    def __f1(self):
        print('f1')
    def f2(self):
        print(self.__n,self.__x)
abx=Foo(3,2)
abx.f2()
abx.__name=123  #{'_Foo__x': 3, 'y': 2, '__name': 123} #外部定义后,属性不会被隐藏
print(Foo.__dict__)
print(abx.__dict__)  #{'_Foo__x': 3, 'y': 2}

进一步说明隐藏的含义

class Foo:
    def f1(self):
        print('foo.f1')
    def f2(self):
        print('foo.f2')
        self.f1()  #b.f1()
class Bar(Foo):
    def f1(self):
        print('bar.f1')
b=Bar()
b.f2()
>>>foo.f2  
>bar.f1   #结果是打印bar.f1
>
#使用隐藏之后
class Foo:
    def __f1(self):
        print('foo.f1')
    def f2(self):
        print('foo.f2')
        self.__f1()  #self._Foo__f1()  #这种隐藏只对外不对内,因为类内部定义的属性在定义类的阶段统一发送变形
class Bar(Foo):
    def __f1(self): #self._Bar__f1()
        print('bar.f1')
b=Bar()
b.f2()
#>foo.f2
#>foo.f1  
封装的真正意义
封装数据属性的目的

外部无法直接访问数据属性,类内部开放接口,然后可以在接口内严格控制外部对属性的增删改查操作

class  People:
    def __init__(self,name,age):
       self.set_info(name,age)  #在类的内部定义方法,严格控制传入的参数

    def tell_info(self):
        print('name:%s 年龄:%s' %(self.__name,self.__age))
    def set_info(self,name,age):
        if type(name) is not str:
            raise TypeError('name not is str')
        if type(age) is not int:
            raise TypeError('age not is int ')
        self.__name=name
        self.__age=age
p=People('egon',19)
# print(p.name)  #p的属性name,age不能直接在外部使用
# p.tell_info()
p.set_info('lqx',12)  #在接口内严格控制对属性的增删改查的操作
p.tell_info()
# p.set_info(123,123)
封装方法的目的

隔离复杂度

#取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
#对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
#隔离了复杂度,同时也提升了安全性
class ATM:
    def __card(self):
        print('卡')
    def __auth(self):
        print('用户认证')
    def __input(self):
        print('输入取款金额')
    def __print_bill(self):
        print('打印账单')
    def __take_money(self):
        print('取款')
    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()
p=ATM()
p.withdraw()
封装之property装饰器

特性property:property是一种特殊的属性,访问它时会执行一段功能(函数)饭后返回值

class People:
    def __init__(self,name,age,height,weight):
        self.name=name
        self.age=age
        self.height=height
        self.weight=weight
    @property  #函数属性的返回值,转换为数据属性
    def bmi(self):
        return self.weight / (self.height **2)
egon=People('lqx',18,1.70,70)
# print(egon.bmi())
egon.height=1.75
# print(egon.bmi()) #不加property装饰器,每次看都是需要调用class初始化出来的对象的函数属性
print(egon.bmi)  #加上property装饰器,把对象的方法转换为数据属性
name.setter修改对象的属性值
class Foo:
    def __init__(self,name):
        self.__name=name

    @property  #针对查看属性的行为,并且不能修改属性
    def name(self):
        return self.__name

    @name.setter 
    def name(self,value):
        if not isinstance(value,str): #isinstance判断字符类型,value是不是str
            raise TypeError('%s must be str' %value)
        self.__name=value

    @name.deleter
    def name(self):
        # del self.name
        raise TypeError('Can not delete')
f=Foo('lqx')
# print(f.name)
# # f._Foo__NAME='000' 直接修改__dict__中的值
# print(f.__dict__)
# f.name='1231'  #使用装饰器name.setter,修改_FOO__NAME的值
# print(f.name)
# print(f.__dict__)

del f.name   #使用装饰器name.deleter不能直接在外部删除函数的属性值

绑定方法与非绑定方法

类中定义的函数分成两大类
绑定方法:(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)
1、绑定到类的方法:用classmethod装饰器装饰的方法
    为类量身定制
    类.boud_method(),自动将类当作第一个参数传入
    (其实对象也可调用,但仍将类当作第一个参数传入)
2、绑定到对象的方法:没有被任何装饰器装饰的方法
    为对象量身定制
    对象.boud_method(),自动将对象当作第一个参数传入
    (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
非绑定方法:(用staticmethod装饰器装饰的方法)
1、不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已
注意的是;与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值的一说
import setting
import hashlib
import time
class Mysql:
    def __init__(self,host,port):
        self.host=host
        self.port=port
    # def func(self):  #默认是绑定给对象的
    #     print('%s 说,123' %self.name)

    @classmethod  #使用装饰器,绑定给类的方法,对象也可以调用,默认第一参数是类
    def from_conf(cls):
        return cls(setting.HOST,setting.PORT)

    @staticmethod #使用装饰器,不绑定给任何类,或者对象的方法
    def create_id(n):
        m=hashlib.md5()
        m.update(str(time.clock() +n).encode('utf-8')) #脚本执行的时间
        return m.hexdigest()

#绑定给类的方法
conn=Mysql.from_conf()
print(Mysql.from_conf())
print(conn.host,conn.port)
conn.from_conf()  #对象也可以调用,但是默认传入的参数仍然是类
#不绑定给任何类或者对象的打印
print(Mysql.create_id(9))
print(conn.create_id(1))

反射

通过字符串来反射到对象,或者类的属性
class Foo:
    def __init__(self,name):
        self.name=name
    def f1(self):
        print(123)
        pass
obj=Foo('egon')
print(obj.name) # 原理:在obj.__dict__['name']中访问一个key
hasattr(object,name)

判断object中有没有一个name字符串对应的方法或者属性

print(hasattr(obj,'name'))
print(hasattr(obj,'age'))
getattr(object,name,default=None)

str类型的数值反射到class中并取出方法的内存地址并赋值

if hasattr(obj,'f1'):
    f=getattr(obj,'f1')
    f()
getattr(obj,'f2',None) #如果没有值那么就返回None
setattr(x,y,v)

setattr(x,y,v) 修改属性的值,(对象,修改的属性,需要修改为什么值)

setattr(obj,'name','dddd')  #修改属性的值
print(obj.__dict__)
delattr(x,y)

delattr(x,y) #删除对象的属性(对象,要删除的对象的属性)

delattr(obj,'name')
print(obj.__dict__)
class Ftpclient:
    def __init__(self,host,port):
        self.__host=host
        self.__port=port

    def interactive(self):
        while True:
            cmd=input('>>>:').strip()
            if not cmd:continue
            cmd_l=cmd.split()
            if hasattr(self,cmd_l[0]):
                par=getattr(self,cmd_l[0],None)  #使用getattr拿到字符串对应的方法
                par()
    def get(self):
        print('get')
    def put(self):
        print('put')
client=Ftpclient('1.1.1.1',21)
client.interactive()

内置函数补充

isinstance:数据类型判断
l=list([])
print(type(l) is list)
#用isinstance来进行数值类型判断
print(isinstance(l,list))
issubclass:类关系判断
class Foo:
    pass

class Bar(Foo):
    pass
print(issubclass(Bar,Foo))   #Bar 是不是Foo的子类

类的内置方法

_str_

函数的return的返回值默认是str类型

l=list([1,2,3,4]) #实例化过程,定一个list的类,然后创造出一个l的对象
print(l)

class Foo:
    pass
obj=Foo()
print(obj)

#打印对象的时候不需要打印类的内存地址,需要打印出来对象的属性
class People:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self): #默认打印出来str的值是一个内存地址
        return  '<name:%s age:%s>' %(self.name,self.age)
lqx=People('lqx',12)
print(lqx) #把__str__的返回值,返回给对象
_del_
析构方法,当对象在内存中被释放时,自动触发执行。

注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义del,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了del

class Foo:

    def __del__(self):
        print('执行我啦')

f1=Foo()
del f1
print('------->')

#输出结果
执行我啦
------->
#在回收python系统申请的资源时,会先执行__del__的操作,回收系统资源
class Foo:

    def __del__(self):
        print('执行我啦')

f1=Foo()
# del f1
print('------->')

#输出结果
------->
执行我啦
#python脚本执行完成后,会自动回收python申请的资源,在回收时,会先去执行__del__的操作

异常处理

什么是异常?
异常是错误发生的信号,一旦程序出错,就会产生一个异常,应用程序未处理该异常
异常边会抛出,程序随之终止
常见的异常类型
语法错误
应该在程序运行前修正
if 1 > 2:
    pass('xxx') #SyntaxError: invalid syntax
逻辑错误
x  #NameError: name 'x' is not defined

l=[]
l[2]  #IndexError: list index out of range

class Foo:
    pass
Foo.s   #AttributeError: type object 'Foo' has no attribute 's'

k={'x':1}
k['1']   #KeyError: '1'

1/0  #ZeroDivisionError: division by zero

for i in 3:  #TypeError: 'int' object is not iterable
    pass

age=input('>>')
age=int(age)   #ValueError: invalid literal for int() with base 10: 'as'
如何处理异常
try的使用
try:...except xxxError:
try:...except xxxError as e: print(e)  #打印报错内容
try:...except xxxError as e: print(e)  else: print('没有异常才触发')
try:...finally: print('有没有异常都触发')
print('====>start<====')
try:
    l=[]
    # print(l[1])
    print('====>1')
    d={}
    # d['2']
    print('====>2')
except IndexError as e:
    print('====>',e)
except KeyError as e:   #可以像elif一样可以写多个匹配
    print('====>',e)
except Exception as e:   #万能异常处理方式Exception
    print('万能异常',e)
else:
    print('没有异常发生的时候触发')
finally:    #有没有异常都触发的一个方法
    print('有没有异常都触发')
print('=====>end<=====')

#finally的使用
try:
    conn=connect('1.1.1.1',3306)
    conn.execute('select * from t1;')
finally:   #自动回收系统资源
    conn.close()
raise 和assert的使用
#主动抛出一个异常
stus=['egon','lqx']
ip_list=[
    '1.1.1.1:8080',
    '2.2.2.2:8090'
]
if len(ip_list) ==0:
    raise TypeError   #主动抛出一个异常
assert len(ip_list)  >0    #条件必须成立,否则抛出一个异常:assert len(ip_list)  >0   AssertionError
print('从ip_list取出ip地址,验证可用性')
自定义异常
自定义一个异常:必须要先继承python自带的异常处理class
#自定义一个异常:必须要先继承python自带的异常处理class
class MyException(BaseException):
    def __init__(self,msg):
        super(MyException,self).__init__()   #调用父类的初始化方法
        self.msg=msg
raise MyException('类型出错')  #异常的值
'''
Traceback (most recent call last):
  File "D:/python20期课程/day8/1、异常处理.py", line 132, in <module>
    raise MyException('类型出错')  #异常的值
__main__.MyException          #不加__str__打印出来的是一个对象
'''

class MyException(BaseException):
    def __init__(self,msg):
        super(MyException,self).__init__()   #调用父类的初始化方法
        self.msg=msg
    def __str__(self):   #加上__str__会在执行类的时候主动返回__str__的return的结果,__str__返回值必须是一个str类型
        return '<%s>' %self.msg
raise MyException('类型出错')  #异常的值
'''
Traceback (most recent call last):
  File "D:/python20期课程/day8/1、异常处理.py", line 144, in <module>
    raise MyException('类型出错')  #异常的值
__main__.MyException: <类型出错>    #加上__str__打印出来的是对象的值
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值