Python魔法方法 容器部方法详解
这篇文章主要介绍了Python魔法方法容器部方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
为了加深印象,也为了以后能够更好的回忆,还是记录一下。
序列(类似集合,列表,字符串),映射(类似字典)基本上是元素的集合,要实现他们的基本行为(协议),不可变对象需要两个协议,可变对象需要4个协议。
- __len__(self):返回元素的数量,(为不可变对象需要的协议之一)=====>len
- __iter__返回一个迭代器,具有了__next__方法后,给for使用。
- __contains__代表in的意思xx.__contains__(22)==>22inxx一个效果
- __getitem__(self,key)或者__getitem__(self,index),返回执行输入所关联的值(为不可变对象需要的协议之一)
- __setitem__(self,key,values)或者__setitem__(self,index,values),设置指定输入的值对应的values
- __delitem__(self,key)删除指定key的值
- __missing__这个有意思,跟__getattr__有的一比,是找不到这个key,触发条件。前面用列表测试了,晕死了(只对字典有效。)
- __del__,析构函数当这个类不存在实例对象时执行。
下面我编写一个自定义类似列表的类,实例后该类默认前面有10个None参数,且不能删除前面5个空None。(随口说的,开始写了)
defcheck_index(index): ifindex<5: raiseIndexError('indexmustgreaterthan10') classS_List: def__init__(self): self.ll=[None]*10 def__len__(self):#提取参数长度 returnlen(self.ll) def__getitem__(self,index):#取出参数 returnself.ll[index] def__setitem__(self,index,value):#设置参数 check_index(index) self.ll[index]=value def__delitem__(self,index): check_index(index) self.ll.pop(index) def__str__(self):#打印对象时,输出列表本身 returnstr(self.ll) def__del__(self):#没有手工删除在程序结束时释放 print('我被释放了!') sl=S_List() delsl[3] print(isinstance(sl,S_List)) print(f'输出原始数据:{sl}') sl[6]='six' print(f'修改后原始数据:{sl}') print(f'随便取一个值:{sl[1]}') delsl[6] print(f'第二次修改后原始数据:{sl}') delsl[3] #sl[4]='oh' print(sl)
正常输出:
True 输出原始数据:[None,None,None,None,None,None,None,None,None,None] 修改后原始数据:[None,None,None,None,None,None,'six',None,None,None] 随便取一个值:None 第二次修改后原始数据:[None,None,None,None,None,None,None,None,None] [None,None,None,None,None,None,None,None,None] 我被释放了!
报错提示:
Traceback(mostrecentcalllast): File"/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py",line81,indelsl[3] File"/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py",line73,in__delitem__ check_index(index) File"/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py",line53,incheck_index raiseIndexError('indexmustgreaterthan10') IndexError:indexmustgreaterthan10 我被释放了!
这个是自定义的一个基本没有什么方法的伪字典,不能增加元素,而且index,count等方法由于没有写入都无法使用。
好的方式是可以继承list或者dict的类,在里面对需要的条件进行修改限制,这样的话,实例出来的对象可以继承原来的全部方法。
插入一个直接不用初始化自定义变量,直接借用__dict__来实现伪字典型的取值复制。
classIi: def__getitem__(self,item): returnself.__dict__[item] def__setitem__(self,key,value): self.__dict__[key]=value li=Ii() li[3]=5 print(li[3]) #5
这次我可以正真的定义个超级列表,根据我的需要。现在要求这个列表初始化有5个None元素,前面5个元素不能修改,后面添加的元素必须为str
defcheck_str(params): ifnotisinstance(params,str): raiseValueError('parametersmustisstring') defcheck_index(index): ifindex<5: raiseIndexError('indexmustgreaterthan10') classSuper_List(list): def__init__(self): super(Super_List,self).__init__()#调用父类初始化 self+=[None]*5#对初始化的参数进行修改 defappend(self,*args):#对append进行参数限制 foriinargs: check_str(i) returnsuper(Super_List,self).append(*args) definsert(self,index,*args):#对insert的参数(索引及插入元素)进行限制 check_index(index)#判断插入位置 foriinargs: check_str(i) returnsuper(Super_List,self).insert(index,*args) defextend(self,*args):#对扩张的列表元素进行判断 temp=args[0] foriintemp: check_str(i) super(Super_List,self).extend(*args) def__delitem__(self,index):#对del命令的索引进行判断 check_index(index) super(Super_List,self).__delitem__(index) defclear(self):#禁止使用clear命令 raiseTypeError('Nopermission') ss_l=Super_List() print(ss_l) ss_l.append('1') ss_l.insert(5,'a') ss_l.extend(['a','b','c']) ss_l.clear() print(ss_l)
写了快半个小时,感觉列表的增加与删除命令很多,所有有一些命令没有重写,但逻辑还是一样的。
如果向在有人访问参数的时候,自动执行某些命令,可以写在__getitem__下面。
跟新后,添加一个__missing__感觉还是非常有意思的。
classDict(dict): def__init__(self,*args,**kwargs): #self.x=12 super(Dict,self).__init__(*args,**kwargs) def__missing__(self,key): self[key]=None returnself[key] l=Dict(((1,2),(2,3))) print(l) print(l[8]) print(l)
{1:2,2:3} None {1:2,2:3,8:None}
有点像字典的内置方式setdefault,我看能不能改成一样的。
已经写完了,通过[]取值。
#-*-coding:utf-8-*- classDict(dict): def__init__(self,*args,**kwargs): super(Dict,self).__init__(*args,**kwargs) def__missing__(self,item): #判断进来的参数是不是字符串,如果是字符串说明就是对象主动调用__missing__进来的 #非__getitem__导入的 ifisinstance(item,str): self[item]='DefaultEmpty' returnself[item] #如果对象非字符串,明显说明是__getitem__导入的,判断长度就可以 else: key,value=item self[key]=value#自身进行赋值 returnself[key]#返回value def__getitem__(self,item): ifnotisinstance(item,tuple):#传进来的item进行判断,如果非元祖,直接调用父类绑定self方法返回 returnsuper(Dict,self).__getitem__(item) eliflen(item)==2andisinstance(item,tuple):#如果是元祖,又是2位长度的,进行赋值。其实感觉元祖判断没有好像也没关系 k,_=item ifkinself: returnsuper(Dict,self).__getitem__(k)#如果k在self里面继续调用父类绑定self方法返回 else: res=self.__missing__(item)#否则调用自身的__missing returnres else: raiseTypeError('inputpatternerror')#元素数量超过2个,直接报错 l=Dict((('name','sidian'),('age',99))) print(l) print(l['name','wudian']) print(l['addr','杭州']) print(l['hobby']) print(l)
{'name':'sidian','age':99} sidian 杭州 DefaultEmpty {'name':'sidian','age':99,'addr':'杭州','hobby':'DefaultEmpty'}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。