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 相关文章推荐
python操作MySQL数据库具体方法
Oct 28 Python
Python实现的石头剪子布代码分享
Aug 22 Python
安装dbus-python的简要教程
May 05 Python
Python编程之列表操作实例详解【创建、使用、更新、删除】
Jul 22 Python
python之Character string(实例讲解)
Sep 25 Python
python绘制立方体的方法
Jul 02 Python
Python使用分布式锁的代码演示示例
Jul 30 Python
浅谈Python批处理文件夹中的txt文件
Mar 11 Python
Python 虚拟空间的使用代码详解
Jun 10 Python
使用python检查yaml配置文件是否符合要求
Apr 09 Python
pytorch查看模型weight与grad方式
Jun 24 Python
python 如何执行控制台命令与操作剪切板
May 20 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/07/19 PHP
解析如何在PHP下载文件名中解决乱码的问题
2013/06/20 PHP
PHP中exec函数和shell_exec函数的区别
2014/08/20 PHP
php5.3提示Function ereg() is deprecated Error问题解决方法
2014/11/12 PHP
php str_replace替换指定次数的方法详解
2017/05/05 PHP
Javascript学习笔记5 类和对象
2010/01/11 Javascript
用jQuery扩展自写的 UI导航
2010/01/13 Javascript
JavaScript基础语法让人疑惑的地方小结
2012/05/23 Javascript
基于javascript 闭包基础分享
2013/07/10 Javascript
调用innerHTML之后onclick失效问题的解决方法
2014/01/28 Javascript
js获取上传文件大小示例代码
2014/04/10 Javascript
分享纯手写漂亮的表单验证
2015/11/19 Javascript
js一维数组、多维数组和对象的混合使用方法
2016/04/03 Javascript
AngularJS 自定义指令详解及示例代码
2016/08/17 Javascript
jquery实现超简单的瀑布流布局【推荐】
2017/03/08 Javascript
微信小程序 按钮滑动的实现方法
2017/09/27 Javascript
vue脚手架搭建过程图解
2018/06/06 Javascript
element UI upload组件上传附件格式限制方法
2018/09/04 Javascript
angular将html代码输出为内容的实例
2018/09/30 Javascript
如何使用Node.js爬取任意网页资源并输出PDF文件到本地
2019/06/17 Javascript
微信小程序实现类似微信点击语音播放效果
2020/03/30 Javascript
Vue路由对象属性 .meta $route.matched详解
2019/11/04 Javascript
JavaScript实现随机点名器
2020/03/25 Javascript
JS遍历树层级关系实现原理解析
2020/08/31 Javascript
Python多线程爬虫简单示例
2016/03/04 Python
使用Python脚本zabbix自定义key监控oracle连接状态
2019/08/28 Python
Python检测端口IP字符串是否合法
2020/06/05 Python
THE OUTNET英国官网:国际设计师品牌折扣网站
2016/08/14 全球购物
幼儿园大班新学期寄语
2014/01/18 职场文书
放飞蜻蜓反思
2014/02/05 职场文书
争当四好少年演讲稿
2014/09/13 职场文书
少年派的奇幻漂流观后感
2015/06/08 职场文书
警示教育观后感
2015/06/17 职场文书
幼儿园秋季开学通知
2015/07/16 职场文书
2015年大学迎新工作总结
2015/07/16 职场文书
高中生军训感言
2015/08/01 职场文书