博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python进阶之魔法函数
阅读量:7036 次
发布时间:2019-06-28

本文共 3638 字,大约阅读时间需要 12 分钟。

python的几个魔法函数

__repr__

Python中这个__repr__函数,对应repr(object)这个函数,返回一个可以用来表示对象的可打印字符串.

如果我们直接打印一个类,向下面这样

class A():    def __init__(self,name=None,id=1):        self.id=id        self.name=nameif __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 itemif __name__ == '__main__':    a=A('lisa','123')    print(a['name'])    print(a[124])复制代码

输出

name124复制代码

实例对象的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])复制代码

输出

lisakeyerror:123复制代码

输出了lisa和一个异常,改后的getitem做了什么事呢,

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

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

import collectionsCard = 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():    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():    def __init__(self):        self.a_list = range(10)    def __setitem__(self, key, value):        self.__dict__[key] = valuedef 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)复制代码

输出

新加入函数c123复制代码

__delitem__

执行del函数的时候会调用,如果继承了 继承

abc.MutableSequence的类就必须实现 __delitem__ 方法,这是 MutableSequence 类的一个抽象方法。

__eq__

a == b等同于a.__eq__(b)。

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

转载地址:http://eqnal.baihongyu.com/

你可能感兴趣的文章
Sharing A Powerful Tool For Calculate Code Lines
查看>>
【循序渐进学Python】8.面向对象的核心——类型(下)
查看>>
一致性Hash
查看>>
过 DNF TP 驱动保护(一)
查看>>
错误 1 在应用程序级别之外使用注册为 allowDefinition='
查看>>
获取系统开机的时间(Windows、Linux)
查看>>
牛人博客网址
查看>>
(转载)Java日期格式化及其使用例子收集
查看>>
LeetCode:Pow(x, n)
查看>>
你所不知道的JavaScript数组
查看>>
[Android Pro] root用户删除文件提示:Operation not permitted
查看>>
strncpy 引起的思考,重新认识了strncpy这个函数【转】
查看>>
A Simple GPS Application Based on Microsoft.WindowsMobile.Samples.Location
查看>>
最简单的基于FFmpeg的AVDevice例子(读取摄像头)【转】
查看>>
Ruby之入门(一)
查看>>
Spark shell的实例操作
查看>>
跳台阶问题
查看>>
MD5算法的C++实现[转载]
查看>>
Eclipse 和 MyEclipse 有什么不同?
查看>>
源代码编译安装 PHP5.5.0,解决curl_exec訪问HTTPS返回502错误的问题
查看>>