广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python魔法方法-自定义序列详解
  • 743
分享到

python魔法方法-自定义序列详解

自定义序列详解 2022-06-04 18:06:51 743人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。 如果要实现这个功能,就要遵循 Python 的相关

自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。

如果要实现这个功能,就要遵循 Python 的相关的协议。所谓的协议就是一些约定内容。例如,如果要将一个类要实现迭代,就必须实现两个魔法方法:__iter__、next(python3.x中为__new__)。__iter__应该返回一个对象,这个对象必须实现 next 方法,通常返回的是 self 本身。而 next 方法必须在每次调用的时候都返回下一个元素,并且当元素用尽时触发 StopIteration 异常。

而其实 for 循环的本质就是先调用对象的__iter__方法,再不断重复调用__iter__方法返回的对象的 next 方法,触发 StopIteration 异常时停止,并内部处理了这个异常,所以我们看不到异常的抛出。

这种关系就好像接口一样,如果回顾以前几篇的魔法方法,可以发现许多的内置函数得到的结果就是相应的魔法方法的返回值。

下面是一下相关的魔法方法:

•__len__(self)

•返回容器的长度。可变和不可变容器都要实现它,这是协议的一部分。

•__getitem__(self, key)

•定义当某一项被访问时,使用self[key]所产生的行为。这也是可变容器和不可变容器协议的一部分。如果键的类型错误将产生TypeError;如果key没有合适的值则产生KeyError。

•__setitem__(self, key, value)

•定义当一个条目被赋值时,使用self[key] = value所产生的行为。这也是可变容器协议的一部分。而且,在相应的情形下也会产生KeyError和TypeError。

•__delitem__(self, key)

•定义当某一项被删除时所产生的行为。(例如del self[key])。这是可变容器协议的一部分。当你使用一个无效的键时必须抛出适当的异常。

•__iter__(self)

•返回一个容器迭代器,很多情况下会返回迭代器,尤其是当内置的iter()方法被调用的时候,以及当使用for x in container:方式循环的时候。迭代器是它们本身的对象,它们必须定义返回self的__iter__方法。

•__reversed__(self)

•实现当reversed()被调用时的行为。应该返回序列反转后的版本。仅当序列是有序的时候实现它,例如列表或者元组。

•__contains__(self, item)

•定义了调用in和not in来测试成员是否存在的时候所产生的行为。这个不是协议要求的内容,但是你可以根据自己的要求实现它。当__contains__没有被定义的时候,Python会迭代这个序列,并且当找到需要的值时会返回True。

•__missing__(self, key)

•其在dict的子类中被使用。它定义了当一个不存在字典中的键被访问时所产生的行为。(例如,如果我有一个字典d,当"george"不是字典中的key时,使用了d["george"],此时d.__missing__("george")将会被调用)。

下面是一个代码示例:


class Foo(object):
  def __init__(self, key, value):
    self.key = []
    self.value = []
    self.key.append(key)
    self.value.append(value)

  def __len__(self):
    return len(self.key)

  def __getitem__(self, item):
    try:
      __index = self.key.index(item)
      return self.value[__index]
    except ValueError:
      raise KeyError('can not find the key')

  def __setitem__(self, key, value):
    if key not in self.key:
      self.key.append(key)
      self.value.append(value)
    else:
      __index = self.key.index(key)
      self.value[__index] = value

  def __delitem__(self, key):
    try:
      __index = self.key.index(key)
      del self.key[__index]
      del self.value[__index]
    except ValueError:
      raise KeyError('can not find the key')

  def __str__(self):
    result_list = []
    for index in xrange(len(self.key)):
      __key = self.key[index]
      __value = self.value[index]
      result = __key, __value
      result_list.append(result)
    return str(result_list)

  def __iter__(self):
    self.__index = 0
    return self

  def next(self):
    if self.__index == len(self.key):
      self.__index = 0
      raise StopIteration()
    else:
      __key = self.key[self.__index]
      __value = self.value[self.__index]
      result = __key, __value
      self.__index += 1
      return result

  def __reversed__(self):
    __result = self.value[:]
    __result.reverse()
    return __result

  def __contains__(self, item):
    if item in self.value:
      return True
    else:
      return False

这里创建一个模拟字典的类,这个类的内部维护了两个列表,key 负责储存键,value 负责储存值,两个列表通过索引的一一对应,从而达到模拟字典的目的。

首先,我们看看__len__方法,按照协议,这个方法应该返回容器的长度,因为这个类在设计的时候要求两个列表必须等长,所以理论上返回哪个列表的长度都是一样的,这里我选择返回 key 的长度。

然后是__getitem__方法。这个方法会在a['scolia']时,调用a.__getitem__('scolia')。也就是说这个方法定义了元素的获取,我这里的思路是先找到 key 列表中建的索引,然后用索引去 value 列表中找对应的元素,然后将其返回。然后为了进一步伪装成字典,我捕获了可能产生的 ValueError (这是 item 不在 key 列表中时触发的异常),并将其伪装成字典找不到键时的 KeyError。

理论上只要实现了上面两个方法,就可以得到一个不可变的容器了。但是我觉得并不满意所以继续拓展。

__setitem__(self, key, value)方法定义了 a['scolia'] = 'Good' 这种操作时的行为,此时将会调用a.__setitem__('scolia', 'good') 因为是绑定方法,所以self是自动传递的,我们不用理。这里我也模拟了字典中对同一个键赋值时会造成覆盖的特性。这个方法不用返回任何值,所以return语句也省略了。

__delitem__(self, key)方法定义了del a['scolia'] 这类操作时候的行为,里面的‘scolia'就作为参数传进去。这里也进行了异常的转换。

只有实现里以上四个方法,就可以当做可变容器来使用了。有同学可能发现并没有切片对应的魔法方法,而事实上,我也暂时没有找到先,这部分内容先搁着一边。

接下来的 __str__ 是对应于 str() 函数,在类的表示中会继续讨论,这里是为了 print 语句好看才加进去的,因为print语句默认就是调用str()函数。

__iter__和next方法在开头的时候讨论过了,这里是为了能让其进行迭代操作而加入的。

__reversed__(self)方法返回一个倒序后的副本,这里体现了有序性,当然是否需要还是要看个人。

__contains__实现了成员判断,这里我们更关心value列表中的数据,所以判断的是value列表。该方法要求返回布尔值。

下面是相应的测试:


a = Foo('scolia', 'good')
a[123] = 321
a[456] = 654
a[789] = 987
print a
del a[789]
print a
for x, y in a:
  print x, y
print reversed(a)
print 123 in a
print 321 in a

查看图片

•__missing__(self, key)


class Boo(dict):
  def __new__(cls, *args, **kwargs):
    return super(Boo, cls).__new__(cls)

  def __missing__(self, key):
    return 'The key(%s) can not be find.'% key

测试:


b = Boo()
b['scolia'] = 'good'
print b['scolia']
print b['123']

查看图片

当然你也可以在找不到 key 的时候触发异常,具体实现看个人需求。

以上这篇python魔法方法-自定义序列详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: python魔法方法-自定义序列详解

本文链接: https://www.lsjlt.com/news/14410.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python魔法方法-自定义序列详解
    自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。 如果要实现这个功能,就要遵循 python 的相关...
    99+
    2022-06-04
    自定义 序列 详解
  • MySQL自定义排序方法详解
    MySQL自定义排序方法详解 在MySQL中,我们通常使用ORDER BY语句进行排序,但是有时候我们需要进行特殊的排序操作,比如按照某些字段的特定值进行排序。这时候就需要用到MySQL中的自定义排序方法。本文将为大家详细介绍MySQL中的...
    99+
    2023-09-03
    数据库 mysql java
  • Python 魔法方法详解
    据说,Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切。 他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Py...
    99+
    2023-01-31
    详解 方法 魔法
  • 课时47:魔法方法:定制序列
    目录:  一、定制序列   二、课时47课后习题及答案   **************** 一、定制序列 **************** 本节要谈的是定制容器,要想成功的实现容器的定制,便需要先谈一谈协议。协议是什么? 协议(Prot...
    99+
    2023-01-30
    课时 序列 方法
  • Python魔方方法详解
    原文链接: https://fishc.com.cn/forum.phpmod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403 魔...
    99+
    2023-01-31
    魔方 详解 方法
  • 详解在Python程序中自定义异常的方法
    通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。 以下为与RuntimeError相关的实例,实例中创建了一个类,基类为RuntimeE...
    99+
    2022-06-04
    自定义 详解 异常
  • Python实现自定义Jupyter魔法命令
    相信大家都用过 jupyter,也用过里面的魔法命令,这些魔法命令都以 % 或者 %% 开头,我们举个例子。 用法还是比较简单的,...
    99+
    2022-11-11
  • 详解Python常用的魔法方法
    目录一、python魔法方法二、运算符重载三、打印操作的魔法方法四、属性操作的魔法方法五、描述符六、定制序列七、迭代器一、python魔法方法 Python的魔法方法会在特定的情况下...
    99+
    2022-11-12
  • php反序列化之魔术方法超详细讲解
    目录php魔术方法__construct()与__destruct()__call__get__set__isset__unset__sleep__wakeup__toString_...
    99+
    2022-11-13
    php反序列化魔术方法 php魔术方法
  • spring-session自定义序列化方法是什么
    本篇内容介绍了“spring-session自定义序列化方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!spring-session...
    99+
    2023-06-22
  • 如何自定义Go Json的序列化方法
    这篇文章主要讲解了“如何自定义Go Json的序列化方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何自定义Go Json的序列化方法”吧!我们知道,通过tag,可以...
    99+
    2023-07-02
  • 自定义Go Json的序列化方法译文
    编译自 Custom JSON Marshalling in Go。 前言 我们知道,通过tag,可以有条件地实现定制Go JSON序列化的方式,比如json:"...
    99+
    2022-11-13
  • 详解Python中魔法方法的使用
    目录迭代器的大小元编程自省(introspection)魔法属性创建自己魔法方法python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两...
    99+
    2022-12-19
    Python魔法方法使用 Python魔法方法
  • python requests自定义方法
    今天改造一个iis6 put上传漏洞的一个脚本,以前使用http.client完成,但个人觉得有一些麻烦,就想用第三方库requests来实现,却发现requests中并没有move方法查了一下,发现requests.requests可以自...
    99+
    2023-01-31
    自定义 方法 python
  • Android自定义Toolbar使用方法详解
    本篇文章介绍: 如何使用Toolbar; 自定义Toolbar; 先来看一看效果,了解一下toolbar; 布局文件: <android.support.v7.wid...
    99+
    2022-06-06
    方法 toolbar Android
  • Flask自定义序列化超详细讲解
    目录1、问题溯源2、flask序列化3、解决方法1、问题溯源 重点就是一个Flask.make_response,这里会做请求的响应的处理。 里面行代码: elif isinsta...
    99+
    2022-11-13
    Flask序列化 Flask自定义序列化
  • 详解Python魔法方法之描述符类
    描述符类要求: 描述符就是将某种特殊类型的类的实例指派给另一个类的属性 至少要实现以下的一个方法: •__get__(self, instance, owner) ...
    99+
    2022-11-12
  • Java实现自定义Excel数据排序的方法详解
    目录1.引入jar包2.自定义排序通常,我们可以在Excel中对指定列数据执行升序或者降序排序,排序时可依据单元格中的数值、单元格颜色、字体颜色或图标等。在需要自定义排序情况下,我们...
    99+
    2022-11-13
  • python进阶之魔术方法详解
    目录一、三个内置函数二、双下划线开头和结尾的方法,叫魔术方法。总结一、三个内置函数 1、@classmethod–类名.属性名 2、@staticmethod&ndash...
    99+
    2022-11-12
  • 详解IntelliJ IDEA 自定义方法注解模板
    最近没啥事开始正式用Eclipse 转入 idea工具阵营,毕竟有70%的开发者在使用idea开发,所以它的魅力可想而知。刚上手大概有一天,就知道它为啥取名为 intelli(智能化)了,确实很智能,这还是一些小小的细节,当然idea也有它...
    99+
    2023-05-30
    intellij idea 注解
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作