专栏名称: Python之禅
分享Python相关技术干货,偶尔扯扯其它的
目录
相关文章推荐
Python爱好者社区  ·  深度学习“四大名著”发布 ·  3 天前  
Python爱好者社区  ·  面向开发者的 NVIDIA ... ·  4 天前  
Python爱好者社区  ·  ML书.pdf ·  6 天前  
Python爱好者社区  ·  王者归来!《一书解决几乎所有机器学习问题》PDF ·  1 周前  
Python爱好者社区  ·  42岁,讲师,因为评职称郁郁寡欢,吃了半年的 ... ·  1 周前  
51好读  ›  专栏  ›  Python之禅

会变 "魔术" 的 Python,文末公布中奖结果

Python之禅  · 公众号  · Python  · 2018-02-02 11:38

正文

Python 最吸引你的地方是什么?

整洁的代码缩进格式?丰富的第三方包?更高的开发效率?还是良好的跨平台性?

这些特性都不足以说明 Python 的优点,最吸引人的应该是动态性所带来的灵活与便利性。

你可能听过说一个词叫做「鸭子类型」,所谓鸭子类型就是只要它走路像鸭子,叫起来像鸭子,那么你就可以认为它是鸭子

而 Python 就有这种魔力使得任何东西都可以是鸭子,这种魔力就源自于语言的动态性, Python 提供了很多魔术方法,使得鸡可以像鸭子一样游泳

所谓魔术方法就是由 Python 内部定义,具有特殊作用的方法,这些方法有一个共同特征,以双下划线开始并以双下划线结尾,比如对象的初始化方法 __init__,是最常用的一个魔术方法(不少初学者以为只有一个下划线,在这栽了跟头

如何使用这些魔术方法呢?

先来看一个例子

我们都知道数字可以相加,字符串也可以相加

>>> 1+2
3
>>> "hello"+" Python"
'hello Python'

列表也可以相加

>>> [1,2,3] + [4,5,6]
[1, 2, 3, 4, 5, 6]

那么两个对象(这里特指类的实例对象)可不可以相加呢?

class Point:
   def __init__(self, x, y):
       self.x = x
       self.y = y

   def __repr__(self):
       return "Point({}, {})".format(self.x, self.y)

>>> (Point(1, 2) + Point(3, 4))
Traceback (most recent call last):
 File "", line 1, in
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
>>>

上面用 Point 类表示坐标系中的一个点,x,y 分别代表横轴和纵轴,两个点相加时报错了,错误日志告诉我们,对于 Point 类不支持 「+」操作。

但如果你实现了魔术方法 __add__ 就可以支持加操作了

class Point:
   ...

   def __add__(self, other):
       assert isinstance(other, Point)
       return Point(self.x + other.x, self.y + other.y)

再来运行:

>>> Point(1, 2) + Point(3, 4)
Point(4, 6)

再举一个例子

我们知道类的属性一般都是用点操作获取属性,例如p.x,p.y,而访问字典对应的key值都是通过 p[‘x’] 或者 p.get(“x”) 来访问的,那字典可不可以用 “.” 的方式获取呢?

>>> d = {"a":"b"}
>>> d.a
Traceback (most recent call last):
 File "", line 1, in
AttributeError: 'dict' object has no attribute 'a'

显然,默认情况下是不允许通过“.”的方式获取的,但是如果你实现了魔术方法__getattr__就可以使用点的方式获取了。

我们自定义一个类,继承 dict,再实现 __getattr__方法就可以用“.”操作了,当属性使用 a.b 的方式访问时,就会调用 __getattr__

>>> class MyDict(dict):
...    def __getattr__(self, item):
...        return self.get(item)
...
>>> d = MyDict(a="b")
>>> d
{'a': 'b'}
>>> d['a']
'b'
>>> d.a
'b'

如果你熟悉 Django 中 Template 语法的话,你现在应该知道为什么字典对象可以使用“.”操作获取里面的元素。

当然,魔术方法远不止这两个,全部加起来有近百来个


  • 关于实例构建与初始化的,比如 __new__,__init__

  • 关于属性访问控制:__getattr__,__setattr__

  • 描述符相关的:__get__, __set__

  • 关于操作容器的: __getitem__,__setitem__

  • 关于上下文管理的:__enter__,__exit__

  • 比较运算符:__cmp__,__eq__,__lt__,__gt__

  • 算术运算符:__add__,__sub__,__mul__,__div__


回复 「magic」可获取一份完整的魔术方法介绍文档。你是使用Python过程,使用过哪些魔术方法来做一些特殊的黑科技操作呢?欢迎留言





周一赠书《年前福利,送书10本》中奖结果出来啦,恭喜以下同学:


@fly swallow

@wowking

@动感光波

@Michael

@李大侠@Mysoul@M-in @yanzu @叶知秋@玉观音
请以上同学尽快微信私信我,把你喜欢的书和联系地址发给我,2天内没发的将取消资格哦,快递要放假了

推荐阅读:

学Python,关注Python之禅