面向对象
面向对象的三大特性:继承,多态,封装
继承与派生
什么是继承
继承是一种新建类的方式,新建的类称为子类,子类会遗传父类的属性,可以减少代码冗余,
在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__打印出来的是对象的值
'''