Python魔法方法 容器部方法详解


Posted in Python onJanuary 02, 2020

这篇文章主要介绍了Python魔法方法 容器部方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

为了加深印象,也为了以后能够更好的回忆,还是记录一下。

序列(类似集合,列表,字符串),映射(类似字典)基本上是元素的集合,要实现他们的基本行为(协议),不可变对象需要两个协议,可变对象需要4个协议。

  • __len__(self):返回元素的数量,(为不可变对象需要的协议之一)=====> len
  • __iter__返回一个迭代器,具有了__next__方法后,给for使用。
  • __contains__ 代表 in的意思 xx.__contains__ (22) ==>22 in xx一个效果
  • __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。(随口说的,开始写了)

def check_index(index):
  if index < 5:
    raise IndexError('index must greater than 10')
 
 
class S_List:
  def __init__(self):
    self.ll = [None] * 10
 
  def __len__(self): # 提取参数长度
    return len(self.ll)
 
  def __getitem__(self, index): # 取出参数
    return self.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): # 打印对象时,输出列表本身
    return str(self.ll)
 
  def __del__(self): # 没有手工删除在程序结束时释放
    print('我被释放了!')
 
sl = S_List()
del sl[3]
 
print(isinstance(sl, S_List))
print(f'输出原始数据:{sl}')
sl[6] = 'six'
print(f'修改后原始数据:{sl}')
print(f'随便取一个值:{sl[1]}')
del sl[6]
print(f'第二次修改后原始数据:{sl}')
del sl[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 (most recent call last):
 File "/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py", line 81, in <module>
  del sl[3]
 File "/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py", line 73, in __delitem__
  check_index(index)
 File "/Users/shijianzhong/Desktop/yunzuan_buy/study_base.py", line 53, in check_index
  raise IndexError('index must greater than 10')
IndexError: index must greater than 10
我被释放了!

这个是自定义的一个基本没有什么方法的伪字典,不能增加元素,而且index,count等方法由于没有写入都无法使用。

好的方式是可以继承list或者dict的类,在里面对需要的条件进行修改限制,这样的话,实例出来的对象可以继承原来的全部方法。

插入一个直接不用初始化自定义变量,直接借用__dict__来实现伪字典型的取值复制。

class Ii:
  def __getitem__(self, item):
    return self.__dict__[item]
  def __setitem__(self, key, value):
    self.__dict__[key] = value
 
li = Ii()
li[3] = 5
print(li[3])
 
# 5

这次我可以正真的定义个超级列表,根据我的需要。现在要求这个列表初始化有5个None元素,前面5个元素不能修改,后面添加的元素必须为str

def check_str(params):
  if not isinstance(params, str):
    raise ValueError('parameters must is string')
   
def check_index(index):
  if index < 5:
    raise IndexError('index must greater than 10')
 
class Super_List(list):
  def __init__(self):
    super(Super_List, self).__init__()   # 调用父类初始化
    self += [None] * 5           # 对初始化的参数进行修改
 
  def append(self, *args):          # 对append进行参数限制
    for i in args:
      check_str(i)
    return super(Super_List, self).append(*args)
 
  def insert(self, index, *args):       # 对insert的参数(索引及插入元素)进行限制
    check_index(index) # 判断插入位置
    for i in args:
      check_str(i)
    return super(Super_List, self).insert(index, *args)
 
  def extend(self, *args):          # 对扩张的列表元素进行判断
    temp = args[0]
    for i in temp:
      check_str(i)
    super(Super_List, self).extend(*args)
   
  def __delitem__(self, index):        # 对del命令的索引进行判断
    check_index(index)
    super(Super_List, self).__delitem__(index)
 
  def clear(self):              # 禁止使用clear命令
    raise TypeError('No permission')
 
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__感觉还是非常有意思的。

class Dict(dict):
  def __init__(self, *args, **kwargs):
    # self.x = 12
    super(Dict, self).__init__(*args, **kwargs)
 
  def __missing__(self, key):
    self[key] = None
    return self[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 -*-

class Dict(dict):
  def __init__(self, *args, **kwargs):
    super(Dict, self).__init__(*args, **kwargs)

  def __missing__(self, item):
    # 判断进来的参数是不是字符串,如果是字符串说明就是对象主动调用__missing__进来的
    # 非__getitem__导入的
    if isinstance(item, str):
      self[item] = 'Default Empty'
      return self[item]
    # 如果对象非字符串,明显说明是__getitem__导入的,判断长度就可以
    else:
      key, value = item
      self[key] = value   # 自身进行赋值
      return self[key]   # 返回value


  def __getitem__(self, item):
    if not isinstance(item, tuple):  # 传进来的item进行判断,如果非元祖,直接调用父类绑定self方法返回
      return super(Dict, self).__getitem__(item)
    elif len(item) == 2 and isinstance(item, tuple):  # 如果是元祖,又是2位长度的,进行赋值。其实感觉元祖判断没有好像也没关系
      k, _ = item
      if k in self:
        return super(Dict, self).__getitem__(k)   # 如果k在self里面继续调用父类绑定self方法返回
      else:
        res = self.__missing__(item)       # 否则调用自身的__missing
        return res
    else:
      raise TypeError('input pattern error')     # 元素数量超过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
杭州
Default Empty
{'name': 'sidian', 'age': 99, 'addr': '杭州', 'hobby': 'Default Empty'}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Eclipse + Python 的安装与配置流程
Mar 05 Python
python迭代器与生成器详解
Mar 10 Python
Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
Mar 19 Python
基于python中theano库的线性回归
Aug 31 Python
Python之inspect模块实现获取加载模块路径的方法
Oct 16 Python
python通过http下载文件的方法详解
Jul 26 Python
基于python分析你的上网行为 看看你平时上网都在干嘛
Aug 13 Python
PyTorch的Optimizer训练工具的实现
Aug 18 Python
python实现俄罗斯方块小游戏
Apr 24 Python
python爬虫用mongodb的理由
Jul 28 Python
使用Python获取爱奇艺电视剧弹幕数据的示例代码
Jan 12 Python
Python开发简易五子棋小游戏
May 02 Python
python 图像的离散傅立叶变换实例
Jan 02 #Python
Python加密模块的hashlib,hmac模块使用解析
Jan 02 #Python
在win64上使用bypy进行百度网盘文件上传功能
Jan 02 #Python
pytorch实现onehot编码转为普通label标签
Jan 02 #Python
pytorch标签转onehot形式实例
Jan 02 #Python
Python socket聊天脚本代码实例
Jan 02 #Python
解决Pytorch训练过程中loss不下降的问题
Jan 02 #Python
You might like
PHP超级全局变量数组小结
2012/10/04 PHP
PHP date()函数警告: It is not safe to rely on the system解决方法
2014/08/20 PHP
PHP中开启gzip压缩的2种方法
2015/01/31 PHP
php获取文件类型和文件信息的方法
2015/07/10 PHP
PHP编写daemon process详解及实例代码
2016/09/30 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
Laravel框架基于ajax实现二级联动功能示例
2019/01/17 PHP
IE8下关于querySelectorAll()的问题
2010/05/13 Javascript
基于Jquery的$.cookie()实现跨越页面tabs导航实现代码
2011/03/03 Javascript
JavaScript调用ajax获取文本文件内容实现代码
2014/03/28 Javascript
浅谈javascript中的call、apply、bind
2016/03/06 Javascript
JavaScript常用正则函数用法示例
2017/01/23 Javascript
jQuery实现简单漂亮的Nav导航菜单效果
2017/03/29 jQuery
JavaScrip数组删除特定元素的几种方法总结
2017/09/06 Javascript
微信小程序CSS3动画下拉菜单效果
2018/11/04 Javascript
vue实现后台管理权限系统及顶栏三级菜单显示功能
2019/06/19 Javascript
layui switch 开关监听 弹出确定状态转换的例子
2019/09/21 Javascript
node.js使用net模块创建服务器和客户端示例【基于TCP协议】
2020/02/14 Javascript
原生js实现自定义滚动条组件
2021/01/20 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 KG VS OG
2018/03/30 DOTA
[01:12:08]LGD vs OG 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.24
2019/09/10 DOTA
一步步教你用Python实现2048小游戏
2017/01/19 Python
python贪婪匹配以及多行匹配的实例讲解
2018/04/19 Python
Python3.9又更新了:dict内置新功能
2020/02/28 Python
Python析构函数__del__定义原理解析
2020/11/20 Python
python中的时区问题
2021/01/14 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
Ralph Lauren法国官网:美国高品味时装品牌
2017/12/08 全球购物
巴西24小时在线药房:Drogasil
2020/06/20 全球购物
求网格中的黑点分布
2013/11/06 面试题
后勤岗位职责
2013/11/26 职场文书
法院答辩状格式
2015/05/22 职场文书
大学班长竞选稿
2015/11/20 职场文书
2016年企业安全生产月活动总结
2016/04/06 职场文书
Python学习之时间包使用教程详解
2022/03/21 Python
用Python仅20行代码编写一个简单的端口扫描器
2022/04/08 Python