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写的ARP攻击代码实例
Jun 04 Python
跟老齐学Python之深入变量和引用对象
Sep 24 Python
python中的装饰器详解
Apr 13 Python
Python3.2模拟实现webqq登录
Feb 15 Python
深入理解NumPy简明教程---数组2
Dec 17 Python
利用python模拟sql语句对员工表格进行增删改查
Jul 05 Python
python爬虫爬取淘宝商品信息(selenum+phontomjs)
Feb 24 Python
django之静态文件 django 2.0 在网页中显示图片的例子
Jul 28 Python
pandas factorize实现将字符串特征转化为数字特征
Dec 19 Python
Python使用configparser读取ini配置文件
May 25 Python
安装pytorch时报sslerror错误的解决方案
May 17 Python
Python关于OS文件目录处理的实例分享
May 23 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文件下载实例代码浅析
2016/08/17 PHP
Dom操作之兼容技巧分享
2011/09/20 Javascript
DOM和XMLHttpRequest对象的属性和方法整理
2012/01/04 Javascript
NodeJS的模块写法入门(实例代码)
2012/03/07 NodeJs
javascript数字格式化通用类 accounting.js使用
2012/08/24 Javascript
如何在JavaScript中实现私有属性的写类方式(一)
2013/12/04 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
jQuery多个input求和的实现方法
2015/02/12 Javascript
javascript实现网页端解压并查看zip文件
2015/12/15 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
老生常谈JavaScript 正则表达式语法
2016/08/20 Javascript
textarea 在浏览器中固定大小和禁止拖动的实现方法
2016/12/03 Javascript
Bootstrap基本插件学习笔记之轮播幻灯片(23)
2016/12/08 Javascript
vue axios用法教程详解
2017/07/23 Javascript
解决vue-router进行build无法正常显示路由页面的问题
2018/03/06 Javascript
详解关于Vue版本不匹配问题(Vue packages version mismatch)
2018/09/17 Javascript
微信小程序tabbar底部导航
2018/11/05 Javascript
WebGL three.js学习笔记之阴影与实现物体的动画效果
2019/04/25 Javascript
Vue CLI项目 axios模块前后端交互的使用(类似ajax提交)
2019/09/01 Javascript
python实现图片压缩代码实例
2019/08/12 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
Python全栈之列表数据类型详解
2019/10/01 Python
关于tensorflow的几种参数初始化方法小结
2020/01/04 Python
Python3操作MongoDB增册改查等方法详解
2020/02/10 Python
使用 Python ssh 远程登陆服务器的最佳方案
2020/03/06 Python
纯css3使用vw和vh实现自适应的方法
2018/02/09 HTML / CSS
DHC美国官网:日本通信销售第一的化妆品品牌
2017/11/12 全球购物
纯净、自信、100%的羊绒服装:360Cashmere
2021/02/20 全球购物
简历中自我评价分享
2013/10/09 职场文书
太行山上观后感
2015/06/05 职场文书
企业安全生产检查制度
2015/08/06 职场文书
2015年幼儿园班主任个人工作总结
2015/10/22 职场文书
初中语文教学研修日志
2015/11/13 职场文书
读《茶花女》有感:山茶花的盛开与凋零
2020/01/17 职场文书
JS数组的常用方法整理
2021/03/31 Javascript
纯html+css实现打字效果
2021/08/02 HTML / CSS