异常处理,内置方法(__new__,__init__,__del__析构方法,单例模式,item系列)
__new__ 创建一个对象
class A:
def __init__(self):
print('in init')
def __new__(cls):
print('in new')
self=object.__new__(cls)#创建一个对象
return self #再返回给self
# object.__new__()#创造对象
a=A
__new__ 构造方法
__init__ 初始化方法
算法和设计模式
设计模式--java开发过程中的一种规范或者设计模式
单例模式*****
创造一个类,这个类始终只有一个实例 ——单例模式
class A:
__mmp=None
def __init__(self,name):
self.name=name
def __new__(cls,*args,**kwars):
if not cls.__mmp:
cls.__mmp=object.__new__(cls)#创造一个空间(对象),cls相当于A
return cls.__mmp#再返回给self
a=A('aaa')
b=A('bbb')
print(a)#打印的是内存地址
print(b)#a,b内存地址相同
print(a.name)#bbb
print(b.name)#bbb
图解
__del__析构方法
对应着一个对象删除之前执行的内容
@property deleter 将方法伪装成属性,执行删除该属性
delattr 使用字符串变量名从命名空间中删除这个变量
class B:
def __del__(self):print('执行我了')#2
b=B()
print(b.__dict__)#{} 1
del b #调用__del__方法,从内存中将d删除 3
print(b.__dict__)
python 解释器
能够主动回收不用的变量
在程序结束的时候所有的数据都会被清除
如果用户主动删除某个变量
那么这个变量将会主动被删除
无论上述哪种方法
在删除一个变量之前都会主动的执行析构方法__del__
class B:
def __init__(self,path):
self.f=open(path)
def __del__(self):#对象删除之前回归一些系统资源
self.f.close()
b=B('userinfo')
item 系列--打辅助的功能
实现了之后,就可以使用对象[]去做一些事情了
lst=[1,2,3] print(lst[0]) dic={'k':'v'} print(dic['k'])
有些内置模块中的内置方法
是依赖__getitem__方法的
或者说是依赖item['a']这种调用方式的
class Item:
def __getitem__(self,item): # ***
print('-->',item)
return 'hello'
def __setitem__(self,key,value):
print(key,value)#a,b
item=Item()
print(item['a'])#--> a hello 此时的item['a']是查看值,调用的是__getitem__函数
item['a']='b'#赋值时调用的是__setitem__函数
print(item['a'])#--> a hello
此时__getitem__和__setitem__没有一点关系
class Item:
def __getitem__(self,item): # ***
print('-->',item)
return self.__dict__[item]
def __setitem__(self,key,value):
self.__dict__[key]=value
print(key,value)#a,b
item=Item()
print(item.__dict__)#{}
# print(item['a'])#不能先调用self.__dict__[item],此时self没值,self.__dict__空间是空的,会报错。
item['a']='b'#赋值时调用的是__setitem__函数
print(item['a'])#--> a hello 此时的item['a']是查看值,调用的是__getitem__函数
此时__getitem__和__setitem__没有一点关系
class Item:?
def __getitem__(self,item): # ***
print('-->',item)
return self.__dict__[item]
def __setitem__(self,key,value):
self.__dict__[key]=value
print(key,value)
def __delitem__(self,key):
self.__dict__.pop(key)
item=Item()
print(item.__dict__)#{}
# print(item['a'])#不能先调用self.__dict__[item],此时self没值,self.__dict__空间是空的,会报错。
item['a']='b'#a,b
print(item['a'])#-->a, b ?
print(item.a)#b ?
print(item.__dict__)#{'a': 'b'}
# del item.a
del item['a']
print(item.__dict__)#{}
python魔法方法__len__,__getitem__,__setitem__,__delitem__
python中除了可以使用内建的类型,如list,tuple,dict,还可以创建自己的对象来实现像这些内建类型的访问,
不过需要在定义类的时候对一些魔法方法逐一实现
class DictDemo:
def __init__(self,key,value):
self.dict = {}
self.dict[key] = value
def __getitem__(self,key):
return self.dict[key]
def __setitem__(self,key,value):
self.dict[key] = value
dictDemo = DictDemo('key0','value0')
print(dictDemo['key0']) #value0
dictDemo['key1'] = 'value1'
print(dictDemo['key1']) #value1
上面的对象就相当于自己创建了一个内建类型相似的字典,当实例中有类似字典的操作的时候
比如:
[python] view plain copy
dictDemo1 = {"key0":"value0"}
print(dictDemo1["key0"]) #value0
实例dictDemo["key0"]就类似上面的的操作,则会自动调用类中定义的方法__getitem__,输出在该方法返回的值
再看看dictDemo["key1"] = "value1",就是字典的操作,会自动调用类中定义的方法__setitem__,来设置相应的值
还有一个__del__,就是当我们要删除一个元素的时候调用(魔法方法会自动调用)
__len__ 如下:
当要使用内建函数len(),而参数是DictDemo的实例的时候,那一定要实现类型中的__len__()方法
[python] view plain copy
class DictDemo:
def __init__(self,key,value):
self.dict = {}
self.dict[key] = value
def __getitem__(self,key):
return self.dict[key]
def __setitem__(self,key,value):
self.dict[key] = value
def __len__(self):
return len(self.dict)
dictDemo = DictDemo('key0','value0')
print(dictDemo['key0']) #value0
dictDemo['key1'] = 'value1'
print(dictDemo['key1']) #value1
print(len(dictDemo)) #2
class List(list):
def append(self, obj):
if type(obj) is str:
super().append(obj)#调用父类的方法,list.append(obj)
else:
# print(f'{obj}不是字符串类型')
print('%s不是字符串类型' % obj)
def show_middle(self):
return self[int(len(self) / 2)]#返回以长度的一半为索引的self的值
li = List('hello word22222')#['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'd', '2', '2', '2', '2', '2', '18', 'abc']
li.append('18')
li.append('abc')
print(li)
print(li.show_middle())#r
扑克牌
from collections import namedtuple
Card = namedtuple('Card',['rank','suit']) # 属性一旦创建就不再改变了,且可以使用属性名直接访问值
card1 = Card('K','黑桃')
print(card1.rank)
print(card1.suit)
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['红心','方板','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
deck = FranchDeck()
# print(deck._cards[0]) #
print(deck[0])
from random import choice
print(choice(deck)) # choice接收iterable,__len__,__getitem__
print(choice(deck._cards)) # choice接收iterable,__len__,__getitem__
print(choice(deck))
print(choice(deck))
print(choice(deck))
print(choice(deck))
from collections import namedtuple
Card = namedtuple('Card',['rank','suit'])
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['红心','方板','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
def __setitem__(self, item,value):
self._cards[item] = value
deck = FranchDeck()
from random import shuffle
# shuffle(deck._cards)
# print(deck._cards)
shuffle(deck) # __len__(self) __getitem__ __setitem__
print(deck._cards)
异常处理
捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
语法:
以下为简单的try....except...else的语法:
try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了'name'异常 except <名字>,<数据>: <语句> #如果引发了'name'异常,获得附加的数据 else: <语句> #如果没有异常发生
try的工作原理:
当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
- 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
- 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。
- 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。
aaa # NameError
int('a') #ValueError
[][4] #IndexError
class A:pass
a = A()
a.name #AttributeError
print('aaaa')
def func():name
def main():
func()
main()
语法错误和逻辑错误
l = [1,2,3,4]
num = input('num : ')
if num.isdigit():
num = int(num)
if num < len(l)-1 and num >0:
print(l[num])
l = [1,2,3,4]
try:
num = int(input('num : '))
print(l[num])
except ValueError:
print('请输入一个数字')
except IndexError:
print('输入的数字超出范围')
try中的代码
一旦在一个地方发生错误
后面的代码就不执行了
会直接跳到except的位置
一个错误类型只能处理一种错误
出现异常之后
会从上到下去匹配except中的error
一旦匹配上就会执行except中的代码
执行完之后不再执行其他except
万能异常
l = [1,2,3,4]
try:
num = int(input('num : '))
print(l[num])
# except: # 所有的错误都能处理
# print('万能的异常')
# except Exception:
# print('万能的异常')
except Exception as e:
print(e)
l = [1,2,3,4]
try:
num = int(input('num : '))
print(l[num])
name
except ValueError:
print('请输入一个数字')
except IndexError:
print('输入的数字超出范围')
except Exception as e:
print(e)
有多个except的时候 万能异常永远在最后
l = [1,2,3,4]
try:
num = int(input('num : '))
print(l[num])
except ValueError:
print('请输入一个数字')
except IndexError:
print('输入的数字超出范围')
else:
print('执行我了')
else中的代码 在try中的代码全部顺利执行之后才执行
如果try中的代码出现错误,那么else就不执行
else中的代码什么时候用呢?
在代码顺利执行的时候,报成功或者报结果的时候使用的
try except格式
try except else格式
l = [1,2,3,4]
try:
f = open('')
# num = int(input('num : '))
# print(l[num])
# except ValueError:
# print('请输入一个数字')
# except IndexError:
# print('输入的数字超出范围')
# else:
# print('执行我了')
finally:
print('finally被执行了')
def func():
try:
f = open('file','w')
content = f.read()
return content
finally:
f.close()
finally
不管代码是否出错,都是一个无论如何会执行的代码
打开的操作系统的资源不管代码执行是否出错,都应该归还
这样的代码就应该写在finally中
try except格式
try except else格式
try except else finally格式
try finally格式
主动的抛一个异常
raise TypeError
raise TypeError('出现了不可思议的TypeError')
条件判断
assert 1==1
print('''aaaaaa''')
class EvaException(BaseException):
def __init__(self,msg):
self.msg=msg
raise EvaException('类型错误')
eva = EvaException('类型错误')
try:
raise EvaException('类型错误')
except EvaException as e:
print(e)
123