Redian新闻
>
Python中常见魔法方法介绍

Python中常见魔法方法介绍

科技

新钛云服已累计为您分享660篇技术干货


什么是魔法方法?

魔法方法(Magic Methods)是Python中的内置函数,一般以双下划线开头和结尾,例如__init____del__等。之所以称之为魔法方法,是因为这些方法会在进行特定的操作时会自动被调用。

在Python中,可以通过dir()方法来查看某个对象的所有方法和属性,其中双下划线开头和结尾的就是该对象的魔法方法。以字符串对象为例:

>>> dir("hello")
['__add__''__class__''__contains__''__delattr__''__doc__''__eq__''__format__''__ge__''__getattribute__',
'__getitem__''__getnewargs__''__getslice__''__gt__''__hash__''__init__''__le__''__len__''__lt__''__mo
d__'
'__mul__''__ne__''__new__''__reduce__''__reduce_ex__''__repr__''__rmod__''__rmul__''__setattr__',
'__sizeof__''__str__''__subclasshook__''_formatter_field_name_split''_formatter_parser''capitalize''center',
'count''decode''encode''endswith''expandtabs''find''format''index''isalnum''isalpha''isdigit''isl
ower'
'isspace''istitle''isupper''join''ljust''lower''lstrip''partition''replace''rfind''rindex''
rjust'
'rpartition''rsplit''rstrip''split''splitlines''startswith''strip''swapcase''title''translate'
'upper''zfill']

可以看到字符串对象有__add__方法,所以在Python中可以直接对字符串对象使用"+"操作,当Python识别到"+"操作时,就会调用该对象的__add__方法。有需要时我们可以在自己的类中重写__add__方法来完成自己想要的效果。

class A(object):
  def __init__(self, str):
      self.str = str

•   def __add__(self, other):
•       print ('overwrite add method')
•       return self.str + "---" + other.str

>>>a1 = A("hello")
>>>a2 = A("world")
>>>print (a1 + a2)
>>>overwrite add method
>>>"hello---world"

我们重写了__add__方法,当Python识别"+"操作时,会自动调用重写后的__add__方法。可以看到,魔法方法在类或对象的某些事件出发后会自动执行,如果希望根据自己的程序定制特殊功能的类,那么就需要对这些方法进行重写。使用魔法方法,我们可以非常方便地给类添加特殊的功能。

常用的魔法方法

1、构造与初始化

__new____init__ 这两个魔法方法常用于对类的初始化操作。上面我们创建a1 = A("hello")时,但首先调用的是__new__;初始化一个类分为两步:    

a.调用该类的new方法,返回该类的实例对象    
b.调用该类的init方法,对实例对象进行初始化。

__new__(cls, *args, **kwargs)至少需要一个cls参数,代表传入的类。后面两个参数传递给__init__。在__new__可以决定是否继续调用__init__方法,只有当__new__返回了当前类cls的实例,才会接着调用__init__。结合__new__方法的特性,我们可以通过重写__new__方法实现Python的单例模式:
class Singleton(object):
  def __init__(self):
      print("__init__")

•   def __new__(cls, *args, **kwargs):
•       print("__new__")
•       if not hasattr(Singleton, "_instance"):
•           print("创建新实例")
•           Singleton._instance = object.__new__(cls)
•       return Singleton._instance

>>> obj1 = Singleton()
>>> __new__
>>> 创建新实例
>>> __init__
>>> obj2 = Singleton()
>>> __new__
>>> __init__
>>> print(obj1, obj2)
>>> (<__main__.Singleton object at 0x0000000003599748>, <__main__.Singleton object at 0x0000000003599748>)

可以看到虽然创建了两个对象,但两个对象的地址相同。
2、控制属性访问这类魔法
方法主要对对象的属性进行访问、定义、修改时起作用。主要有:
__getattr__(self, name): 定义当用户试图获取一个属性时的行为。
__getattribute__(self, name):定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用getattr)。
__setattr__(self, name, value):定义当一个属性被设置时的行为。

当初始化属性时如self.a=a时或修改实例属性如ins.a=1时本质时调用魔法方法self.__setattr__(name,values);当实例访问某个属性如ins.a本质是调用魔法方法a.__getattr__(name)

3、容器类操作    
有一些方法可以让我们自己定义自己的容器,就像Python内置的List,Tuple,Dict等等;容器分为可变容器和不可变容器。
如果自定义一个不可变容器的话,只能定义__len__和__getitem__;定义一个可变容器除了不可变容器的所有魔法方法,还需要定义__setitem__和__delitem__;如果容器可迭代。还需要定义__iter__。
__len__(self):返回容器的长度  
__getitem__(self,key):当需要执行self[key]的方式去调用容器中的对象,调用的是该方法    
__setitem__(self,key,value):当需要执行self[key] = value时,调用的是该方法
__iter__(self):当容器可以执行 for x in container:,或者使用iter(container)时,需要定义该方法

下面举一个例子,实现一个容器,该容器有List的一般功能,同时增加一些其它功能如访问第一个元素,最后一个元素,记录每个元素被访问的次数等。
class SpecialList(object):
    def __init__(self, values=None):
        self._index = 0
        if values is None:
            self.values = []
        else:
            self.values = values
        self.count = {}.fromkeys(range(len(self.values)), 0)

    def __len__(self):  # 通过len(obj)访问容器长度
        return len(self.values)

    def __getitem__(self, key):  # 通过obj[key]访问容器内的对象
        self.count[key] += 1
        return self.values[key]

    def __setitem__(self, key, value):  # 通过obj[key]=value去修改容器内的对象
        self.values[key] = value

    def __iter__(self):  # 通过for 循环来遍历容器
        return iter(self.values)

    def __next__(self):
        # 迭代的具体细节
        # 如果__iter__返回时self 则必须实现此方法
        if self._index >= len(self.values):
            raise StopIteration()
        value = self.values[self._index]
        self._index += 1
        return value

    def append(self, value):
        self.values.append(value)

    def head(self):
        # 获取第一个元素
        return self.values[0]
    
    def last(self):
        # 获取最后一个元素
        return self.values[-1]

 这类方法的使用场景主要在你需要定义一个满足需求的容器类数据结构时会用到,比如可以尝试自定义实现树结构、链表等数据结构(在collections中均已有),或者项目中需要定制的一些容器类型。

总结

魔法方法在Python代码中能够简化代码,提高代码可读性,在常见的Python第三方库中可以看到很多对于魔法方法的运用。
因此当前这篇文章仅是抛砖引玉,真正的使用需要在开源的优秀源码中以及自身的工程实践中不断加深理解并合适应用。
了解新钛云服
· 新钛云服成为国内首家荣获 Gartner Customer First 徽章的云和安全管理服务商!
· 新钛云服荣膺“2022爱分析 · IT运维厂商全景报告”云管理平台CMP 代表厂商!
· 新钛云服荣膺第四届FMCG零售消费品行业CIO年会「年度数字化服务最值得信赖品牌奖」
· 新钛云服A轮融资数千万元!获资本和客户双重青睐!
· 新钛云服三周岁,公司月营收超600万元,定下百年新钛的发展目标
· 当IPFS遇见云服务|新钛云服与冰河分布式实验室达成战略协议
· 深耕专业,矗立鳌头,新钛云服获千万Pre-A轮融资
· 新钛云服一周年,完成两轮融资,服务五十多家客户

往期技术干货
· 万字长文:云架构设计原则|附PDF下载
· 万字长文 | 使用 RBAC 限制对 Kubernetes 资源的访问
· 万字长文 | 面向k8s编程,如何写一个Operator
· Terraform 实战 | 万字长文
· 万字长文 | 在 Kubernetes 中部署高可用应用程序的最佳实践!
· CephFS性能基准测试与集群优化 | 万字总结
· 低代码开发,全民开发,淘汰职业程序员!
· 国内主流公有云VPC使用对比及总结
· Ceph OSD故障排除|万字经验总结
· 运维人的终身成长,从清单管理开始|万字长文!
· OpenStack与ZStack深度对比:架构、部署、计算存储与网络、运维监控等
· IT混合云战略:是什么、为什么,如何构建?

点👇分享

戳👇在看

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
Python小技巧:​args 和 kwargs 的乐趣超越TensorFlow、PyTorch,百度飞桨登顶中国市场应用规模第一 | 信通院最新报告Python 中可观测性的 7 个关键部分 | Linux 中国《天才基本法》完结!张子枫学Python的样子,像极了出国后的我自己...2小时完成的第一个副业单子:Python修正excel表格数据以魔法对抗魔法:支持和反对堕胎权的人们开打科技大战午报 | LV老板今年财富蒸发550亿美元;杰尼亚CEO称西装未死;Ralph Lauren中国首家全球旗舰店将开业《黑袍纠察队》其实就是在用魔法打败魔法。胡锡进难得“讲人话” 罕见发“雄文”质疑清零“地球”应该写成the earth还是the Earth?Thonny:在学校教授 Python 编程的理想 IDE | Linux 中国彭博社开源 Memray,一个 Python 内存剖析器 | Linux 中国硬核观察 #739 Python 虽然是最受欢迎的编程语言,但是找工作还是要会点 SQL利用python腾讯在线文档的修改Python批量将Photoshop文件保存为图片防控方针由党的性质和宗旨决定Python证书的含金量高吗?用 Python 测试 API 的 3 种方式 | Linux 中国使用 Python 的 requests 和 Beautiful Soup 来分析网页 | Linux 中国用魔法打败魔法,广西群众太牛逼!机器学习:使用 Python 进行分类 | Linux 中国出口成章:20个常用英文成语Gunicorn 与 Python GIL硬核观察 #645 JavaScript 和 Python 继续统治编程语言,但 Rust 在崛起美国国会通过的【轴心法】全文翻译Python根据经纬度生成并调用地图‘Hot, Hot, Hot’: China Hit with Blistering Heat Wave《天才基本法》揭秘Python真实用法,留学生直呼“上当了”机器学习:使用 Python 进行预测 | Linux 中国看漫画就能学会?最适合留学生快速上手的Python教程来了!修复 Ubuntu Linux 中 “Command ‘python’ not found” 的错误 | Linux 中国吴晓波|“我们这是怎么了?”喜大普奔!Python终行动,天下苦GIL久矣Marcus by Goldman Sachs Savings 银行账户【1.20% APY + 额外1.0% APY三个月】​BatchNorm的“平替”?TUM提出KNConvNets,消除CNN中BatchNorm的缺点
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。