异常处理,内置方法(__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

原文地址:https://www.cnblogs.com/daofaziran/p/9116279.html