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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。