社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 中常用的魔术方法

Python中文社区 • 6 年前 • 628 次点击  

Illustrations by Nikita Pilyukshin

zarten,互联网一线工作者。

博客地址:zhihu.com/people/zarten


概述

python中特殊方法(魔术方法)是被python解释器调用的,我们自己不需要调用它们,我们统一使用内置函数来使用。例如:特殊方法__len__()实现后,我们只需使用len()方法即可;也有一些特殊方法的调用是隐式的,例如:for i in x: 背后其实用的是内置函数iter(x)

下面将介绍一些常用特殊方法和实现。通过实现一个类来说明

常用特殊方法及实现

  • __len__()

一般返回数量,使用len()方法调用。在__len__()内部也可使用len()函数

  1. class Zarten():

  2. def __init__(self, age):

  3. self.age = age

  4. self.brother = ['zarten_1', 'zarten_2']


  5. def __len__(self):

  6. return len(self.brother) #可直接使用len()

  7. # return self.age


  8. z = Zarten(18)

  9. print(len(z))

  • __str__()


对象的字符串表现形式,与__repr__()基本一样,微小差别在于:

1、__str__()用于给终端用户看的,而__repr__()用于给开发者看的,用于调试和记录日志等。

2、在命令行下,实现__str_()后,直接输入对象名称会显示对象内存地址;而实现`repr()后,跟print(对象)效果一样。

3、若这2个都实现,会调用__str_(),一般在类中至少实现__repr__()

  1. class Zarten():

  2. def __repr__(self):

  3. return 'my name is Zarten_1'


  4. def __str__(self):

  5. return 'my name is Zarten_2'


  6. z = Zarten()

  7. print(z)

  1. my name is Zarten_2

  • __iter__()


返回一个可迭代对象,一般跟__next__()一起使用

  1. class Zarten():

  2. def __init__(self, brother_num):

  3. self.brother_num = brother_num

  4. self.count = 0


  5. def __iter__(self):

  6. return self


  7. def __next__(self):

  8. if self.count >= self.brother_num:

  9. raise StopIteration

  10. else:

  11. self.count += 1

  12. return 'zarten_' + str(self.count)



  13. zarten = Zarten(5)

  14. for i in zarten:

  15. print(i)

  • __getitem__()


此特殊方法返回数据,也可以替代__iter_()__next__()方法,也可支持切片

  1. class Zarten():

  2. def __init__(self):

  3. self.brother = ['zarten_1','zarten_2','zarten_3','zarten_4','zarten_5',]


  4. def __getitem__(self, item):

  5. return self.brother[item]


  6. zarten = Zarten()

  7. print(zarten[2])

  8. print (zarten[1:3])


  9. for i in zarten:

  10. print(i)

  • __new__()


__new__()用来构造一个类的实例,第一个参数是cls,一般情况下不会使用。而__init__()用来初始化实例,所以__new__()__init___()先执行。

__new__()不返回,则不会有任何对象创建,__init___()也不会执行;

__new__()返回别的类的实例,则__init___()也不会执行;

用途:可使用__new___()实现单例模式

  1. class Zarten():

  2. def __new__(cls, *args, **kwargs):

  3. print('__new__')

  4. return super().__new__(cls)


  5. def __init__(self, name, age):

  6. print('__init__')

  7. self.name = name

  8. self.age = age


  9. def __repr__(self):

  10. return 'name: %s age:%d' % (self.name,self.age)


  11. zarten = Zarten('zarten', 18)

  12. print(zarten)

  1. __new__

  2. __init__

  3. name:zarten age:18

使用__new__()实现单例模式

  1. class Zarten():

  2. _singleton = None


  3. def __new__(cls, *args, **kwargs):

  4. print('__new__')

  5. if not cls._singleton:

  6. cls._singleton = super().__new__(cls)

  7. return cls._singleton


  8. def __init__(self, name, age):

  9. print('__init__')

  10. self.name = name

  11. self.age = age


  12. def __repr__(self):

  13. return 'name: %s age:%d' % (self. name,self.age)


  14. zarten = Zarten('zarten', 18)

  15. zarten_1 = Zarten('zarten_1', 19)

  16. print(zarten)

  17. print(zarten_1)

  18. print(zarten_1 == zarten)

  1. __new__

  2. __init__

  3. __new__

  4. __init__

  5. name:zarten_1 age:19

  6. name:zarten_1 age:19

  7. True

  • __call__()


实现后对象可变成可调用对象,此对象可以像函数一样调用,例如:自定义函数,内置函数,类都是可调用对象,可用callable()判断是否是可调用对象

  1. class Zarten():


  2. def __init__(self, name, age):

  3. self.name = name

  4. self.age = age


  5. def __call__(self):

  6. print('name:%s age:%d' % (self.name, self.age))



  7. z = Zarten( 'zarten', 18)

  8. print(callable(z))

  9. z()

  • __enter__()


一个上下文管理器的类,必须要实现这2个特殊方法:__enter_()__exit__(),使用with语句来调用。

使用__enter__()返回对象,使用__exit__()关闭对象

  1. class Zarten():


  2. def __init__(self, file_name, method):

  3. self.file_obj = open(file_name, method)


  4. def __enter__(self):

  5. return self.file_obj


  6. def __exit__(self, exc_type, exc_val, exc_tb):

  7. self.file_obj.close()

  8. print('closed')



  9. with Zarten('e:\\test.txt', 'r') as f:

  10. r = f.read()

  11. print(r)

  • __add__()


加法运算符重载以及__radd__()反向运算符重载

当对象作加法时,首先会在“+”左边对象查找__add__(),若没找到则在“+”右边查找__radd__()

  1. class Zarten():


  2. def __init__(self, age):

  3. self.age = age


  4. def __add__(self, other):

  5. return self.age + other


  6. def __radd__(self, other):

  7. return self.age + other




  8. z = Zarten(18)

  9. print(z + 10)

  10. print(20 + z)

  • __del__() 


对象生命周期结束时调用,相当于析构函数


  1. class Zarten():


  2. def __init__(self, age):

  3. self.age = age


  4. def __del__(self):

  5. print('__del__')



  6. z = Zarten(18)

特殊(魔术)方法汇总一览表


热 门 推 荐

用Python创建微信机器人

用Python机器人监听微信群聊

用Python获取摄像头并实时控制人脸

开源项目 | 用Python美化LeetCode仓库

推荐Python中文社区旗下的几个服务类公众号

征稿启事 | Python中文社区有奖征文

▼ 点击成为社区注册会员          「在看」 一下,一起PY!

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/34503
 
628 次点击