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 相关文章推荐
Python with用法实例
Apr 14 Python
Python的Django框架中自定义模版标签的示例
Jul 20 Python
python用10行代码实现对黄色图片的检测功能
Aug 10 Python
简单了解Python下用于监视文件系统的pyinotify包
Nov 13 Python
python3+PyQt5使用数据库窗口视图
Apr 24 Python
mac 安装python网络请求包requests方法
Jun 13 Python
Python爬虫之正则表达式的使用教程详解
Oct 25 Python
Python使用scrapy爬取阳光热线问政平台过程解析
Aug 14 Python
面向对象学习之pygame坦克大战
Sep 11 Python
pygame实现贪吃蛇游戏(上)
Oct 29 Python
Python使用monkey.patch_all()解决协程阻塞问题
Apr 15 Python
python爬虫中抓取指数的实例讲解
Dec 01 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 多进程 解决难题
2009/06/22 PHP
php目录操作函数之获取目录与文件的类型
2010/12/29 PHP
如何取得中文字符串中出现次数最多的子串
2013/08/08 PHP
PHP Session 变量的使用方法详解与实例代码
2013/09/11 PHP
Yii+MYSQL锁表防止并发情况下重复数据的方法
2016/07/14 PHP
PHP标准库(PHP SPL)详解
2019/03/16 PHP
PHP编程一定要改掉的5个不良习惯
2020/09/18 PHP
本人自用的global.js库源码分享
2015/02/28 Javascript
在JavaScript中访问字符串的子串
2015/07/07 Javascript
基于jquery实现图片放大功能
2016/05/07 Javascript
DOM操作和jQuery实现选项移动操作的简单实例
2016/06/07 Javascript
Actionscript与javascript交互实例程序(修改)
2016/09/22 Javascript
JavaScript去掉数组重复项的方法分析【测试可用】
2018/07/19 Javascript
js中比较两个对象是否相同的方法示例
2019/09/02 Javascript
vue+vant实现购物车全选和反选功能
2020/11/17 Vue.js
python实现从一组颜色中找出与给定颜色最接近颜色的方法
2015/03/19 Python
简单介绍Python中的struct模块
2015/04/28 Python
使用python 3实现发送邮件功能
2018/06/15 Python
解决python os.mkdir创建目录失败的问题
2018/10/16 Python
python通过paramiko复制远程文件及文件目录到本地
2019/04/30 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
在TensorFlow中屏蔽warning的方式
2020/02/04 Python
Python定义函数实现累计求和操作
2020/05/03 Python
Python爬虫Scrapy框架CrawlSpider原理及使用案例
2020/11/20 Python
pycharm 2020.2.4 pip install Flask 报错 Error:Non-zero exit code的问题
2020/12/04 Python
python FTP编程基础入门
2021/02/27 Python
css3使用animation属性实现炫酷效果(推荐)
2020/02/04 HTML / CSS
BrandAlley英国:法国折扣奢侈品网上零售商
2017/07/03 全球购物
爱国卫生月实施方案
2014/02/21 职场文书
作文评语大全
2014/04/23 职场文书
幼儿园迎国庆65周年活动策划方案
2014/09/16 职场文书
幼儿教师辞职信范文
2015/03/02 职场文书
英语教师求职信范文
2015/03/20 职场文书
中小企业员工手册范本
2015/05/14 职场文书
浅谈PHP7中的一些小技巧
2021/05/29 PHP
Python接口自动化之文件上传/下载接口详解
2022/04/05 Python