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实现一个简单的能够上传下载的HTTP服务器
May 05 Python
Python中每次处理一个字符的5种方法
May 21 Python
详解Python中的__new__、__init__、__call__三个特殊方法
Jun 02 Python
简单实现python收发邮件功能
Jan 05 Python
Python pyinotify日志监控系统处理日志的方法
Mar 08 Python
python如何生成各种随机分布图
Aug 27 Python
详解Python3 基本数据类型
Apr 19 Python
django 基于中间件实现限制ip频繁访问过程详解
Jul 30 Python
python__new__内置静态方法使用解析
Jan 07 Python
python搜索算法原理及实例讲解
Nov 18 Python
Python图像处理之膨胀与腐蚀的操作
Feb 07 Python
python中 Flask Web 表单的使用方法
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
合作指挥官:孟斯克
2020/03/16 星际争霸
php阳历转农历优化版
2016/08/08 PHP
ThinkPHP实现简单登陆功能
2017/04/28 PHP
使用GruntJS链接与压缩多个JavaScript文件过程详解
2013/08/02 Javascript
jquery 添加节点的几种方法介绍
2013/09/04 Javascript
jquery ajax属性async(同步异步)示例
2013/11/05 Javascript
asp.net+js实现金额格式化
2015/02/27 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
深入浅析JavaScript中的constructor
2016/04/19 Javascript
关于验证码在IE中不刷新的快速解决方法
2016/09/23 Javascript
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
Vue-cli3项目配置Vue.config.js实战记录
2018/07/29 Javascript
从零开始搭建vue移动端项目到上线的步骤
2018/10/15 Javascript
微信小程序开发常见问题及解决方案
2019/07/11 Javascript
layui清除radio的选中状态实例
2019/11/14 Javascript
Javascript模拟实现new原理解析
2020/03/03 Javascript
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
python 调用HBase的简单实例
2016/12/18 Python
Python实现针对给定字符串寻找最长非重复子串的方法
2018/04/21 Python
django静态文件加载的方法
2018/05/20 Python
Python 处理图片像素点的实例
2019/01/08 Python
Python装饰器用法实例分析
2019/01/14 Python
Python 中Django安装和使用教程详解
2019/07/03 Python
Python文件操作方法详解
2020/02/09 Python
Python爬取阿拉丁统计信息过程图解
2020/05/12 Python
Python 随机按键模拟2小时
2020/12/30 Python
如何用Python和JS实现的Web SSH工具
2021/02/23 Python
浅析几个CSS3常用功能的写法
2014/06/05 HTML / CSS
C#面试问题
2016/07/29 面试题
开工典礼策划方案
2014/05/23 职场文书
绘画专业自荐信
2014/07/04 职场文书
人身损害赔偿协议书范本
2014/09/27 职场文书
公司员工辞职信范文
2015/05/12 职场文书
借条如何写
2015/05/26 职场文书
幼儿园老师新年寄语
2015/08/17 职场文书
jQuery实现广告显示和隐藏动画
2021/07/04 jQuery