python 魔法函数实例及解析


Posted in Python onSeptember 25, 2019

python的几个魔法函数

__repr__

Python中这个__repr__函数,对应repr(object)这个函数,返回一个可以用来表示对象的可打印字符串.如果我们直接打印一个类,向下面这样

class A():
  def __init__(self,name=None,id=1):
    self.id=id
    self.name=name

if __name__ == '__main__':
  a=A()
  print(a)

输出结果

<__main__.A object at 0x0000018DF8E7EAC8>

不是很友好,返回了一个对象的内存地址。我们改成下面再次输出

class A():
  def __init__(self,name=None,id=1):
    self.id=id
    self.name=name
  def __repr__(self):
    return "进入函数"

if __name__ == '__main__':
  print(A())

输出结果

进入函数

__str__

class A():
  def __init__(self,name=None,id=1):
    self.id=id
    self.name=name
  def __str__(self):
    return "进入函数"

if __name__ == '__main__':
  print(A())

输出结果

进入函数

比较repr和str

上面我们发现在print的时候,两个魔法函数显示的效果是一样的,那这两个魔法函数区别在哪呢,__repr__和__str__这两个方法都是用于显示的,__str__是面向用户的,而__repr__面向程序员。在print的时候两者项目一样,但是在交互命令下__repr__同样有着print的效果,但是__str__还是输出对象内存地址。也就说在交互式命令下我们可以看到其效果,另外__str__ 方法其实调用了 __repr__ 方法。

__getitem__

如果在类中定义了getitem__()方法,那么他的实例对象(假设为A)就可以这样A[key]取值。当实例对象做A[key]运算时,就会调用类中的__getitem()方法。

class A():
  def __init__(self,name=None,id=1):
    self.id=id
    self.name=name
  def __repr__(self):
    return "进入函数"
  def __getitem__(self, item):
    return item
if __name__ == '__main__':
  a=A('lisa','123')
  print(a['name'])
  print(a[124])

输出

name
124

实例对象的key不管是否存在都会调用类中的__getitem__()方法。而且返回值就是__getitem__()方法中规定的return值。也就是说如果getitem里的方法写的不好就没有了意义了。我们修改下代码,改变getitem的return的值

class A():
  def __init__(self,name=None,id=1):
    self.id=id
    self.name=name
  def __repr__(self):
    return "进入函数"
  def __getitem__(self, item):
    return self.__dict__[item]
if __name__ == '__main__':
  a=A('lisa','123')
  print(a['name'])
  print(a[123])

输出

lisa
keyerror:123

输出了lisa和一个异常,改后的getitem做了什么事呢,self.__dict__,是获取当前实例的所有属性的字典格式,后面的[item]就是取其对于的键值,这里我传了个name,实际就是取name属性的值也就是lisa。对于123因为不存在这个属性所有报错了。这也是字典内部实现的一部分。

再来看一个例子,代码里已经加入了注释:

import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
# 具名元组动态创建一个类Card,并含有两个属性rank和suit
# 用以构建只有少数属性但是没有方法的对象

class FrenchDeck:
  ranks = [str(n) for n in range(2, 11)] + list('JQKA') # 扑克牌2到A组成的列表
  suits = 'spades diamonds clubs hearts'.split() # 四种花色

  def __init__(self):
    self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks] # 笛卡尔积,13*4=52(除去两个王)

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

  def __getitem__(self, position):
    # 调用f[0]时会进入
    return self._cards[position]
if __name__ == '__main__':
  f = FrenchDeck()

  print(f[0])
  # 在这里f[0]实际是f.__getitem__(0)

输出

Card(rank='2', suit='spades')

我们发现这个例子中还有一个__len__,那这个方法是干嘛的呢,我们继续往下看

__len__

在上面的例子中我们使用该方法,这个方法会在什么情况下发生呢,一个小例子来说明。

class B():

class B():
  def __init__(self):
    self.a_list = range(10)
  def __len__(self):
    return len(self.a_list)
if __name__ == '__main__':
   b = B()
   print(len(b))
   #在这里等价于
   #print(b.__len__())

输出

10

我们在调用len方法的时候会调用__len__。

__setitem__

__setitem__(self,key,value):该方法应该按一定的方式存储和key相关的value。在设置类实例属性时自动调用的。

class B():

class B():
  def __init__(self):
    self.a_list = range(10)
  def __setitem__(self, key, value):
    self.__dict__[key] = value
def cfun(a, b, c):
  print("新加入函数c")
if __name__ == '__main__':
  b = B()
  b['a_list'] = "123" # 这个会调用B类的\__setitem_方法_
  B.__setitem__ = cfun # 改变settime方式变为cfun这个函数
  b['a_list'] = "123" # 这次实际会调用cfun函数
  print(b.a_list)

输出

新加入函数c
123

__delitem__

执行del函数的时候会调用,如果继承了 继承abc.MutableSequence的类就必须实现 __delitem__ 方法,这是 MutableSequence 类的一个抽象方法。

__eq__

a == b等同于a.__eq__(b)。你可以在自己的类中定义 __eq__ 方法,决定 == 如何比较实例。如果不覆盖 __eq__ 方法,那么从 object 继承的方法比较

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

Python 相关文章推荐
python3+PyQt5重新实现自定义数据拖放处理
Apr 19 Python
如何在python字符串中输入纯粹的{}
Aug 22 Python
Windows系统下PhantomJS的安装和基本用法
Oct 21 Python
使用Python实现微信提醒备忘录功能
Dec 04 Python
python random从集合中随机选择元素的方法
Jan 23 Python
解决python2 绘图title,xlabel,ylabel出现中文乱码的问题
Jan 29 Python
Django 响应数据response的返回源码详解
Aug 06 Python
Python 获取项目根路径的代码
Sep 27 Python
Python3之乱码\xe6\x97\xa0\xe6\xb3\x95处理方式
May 11 Python
Python日志处理模块logging用法解析
May 19 Python
Python+OpenCV图像处理——打印图片属性、设置存储路径、调用摄像头
Oct 22 Python
Pytorch数据读取之Dataset和DataLoader知识总结
May 23 Python
你还在@微信官方?聊聊Python生成你想要的微信头像
Sep 25 #Python
python并发爬虫实用工具tomorrow实用解析
Sep 25 #Python
Python帮你微信头像任意添加装饰别再@微信官方了
Sep 25 #Python
python异步编程 使用yield from过程解析
Sep 25 #Python
手机使用python操作图片文件(pydroid3)过程详解
Sep 25 #Python
Python缓存技术实现过程详解
Sep 25 #Python
Laravel框架表单验证格式化输出的方法
Sep 25 #Python
You might like
PHP入门学习的几个不错的实例代码
2008/07/13 PHP
PHP框架Swoole定时器Timer特性分析
2014/08/19 PHP
JavaScript的parseInt 进制问题
2009/05/07 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
js异步加载的三种解决方案
2013/03/04 Javascript
JS实现简单的顶部定时关闭层效果
2014/06/15 Javascript
innerHTML动态添加html代码和脚本兼容多个浏览器
2014/10/11 Javascript
jQuery中width()方法用法实例
2014/12/24 Javascript
JS实现仿QQ面板的手风琴效果折叠菜单代码
2015/09/11 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
微信小程序 input输入框详解及简单实例
2017/01/10 Javascript
bootstrap+jQuery实现的动态进度条功能示例
2017/05/25 jQuery
js浏览器滚动条卷去的高度scrolltop(实例讲解)
2017/07/07 Javascript
vuejs前后端数据交互之从后端请求数据的实例
2018/08/11 Javascript
vue实现在一个方法执行完后执行另一个方法的示例
2018/08/25 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
[53:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第三场 6.2
2018/06/03 DOTA
[01:04:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第二场 1月31日
2021/03/11 DOTA
python解析xml文件操作实例
2014/10/05 Python
python ETL工具 pyetl
2020/06/07 Python
如何解决pycharm调试报错的问题
2020/08/06 Python
10个顶级Python实用库推荐
2021/03/04 Python
西班牙床垫网上商店:Colchones.es
2018/05/06 全球购物
英国第一职业高尔夫商店:Clickgolf.co.uk
2020/11/18 全球购物
Linux常见面试题
2016/10/04 面试题
文秘专业大学生求职信
2013/11/10 职场文书
建筑公司文秘岗位职责
2013/11/29 职场文书
厨房管理计划书
2014/04/27 职场文书
学校志愿者活动总结
2014/06/27 职场文书
幼儿园秋季开学通知
2015/07/16 职场文书
小学总务工作总结
2015/08/13 职场文书
范文之农村基层党建工作报告
2019/10/24 职场文书
Appium中scroll和drag_and_drop根据元素位置滑动
2022/02/15 Python
Python中Schedule模块使用详解 周期任务神器
2022/04/19 Python
搭建Yolov5服务器
2022/04/30 Servers
win10如何开启ahci模式?win10开启ahci模式详细操作教程
2022/07/23 数码科技