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  阅读(63)  评论(0)    收藏  举报