引言

  • 魔法函数是Python中定义的,以__开头,__结尾,形如__fun__()的函数,一般使用语言中已经定义好了的即可。
  • 使用这样一些函数,可以让我们自定义的类有更加强大的特性。
  • 魔法函数一般是隐式调用的,不需要我们显示调用。

现在有这么一个类,它维护了一些语言列表。

  1. class Language(object):
  2. def __init__(self, language_list):
  3. self.lans = language_list
  4. # 如果要遍历所有的语言,可以:
  5. language = Language(["Python", "C", "Lisp"])
  6. for lan in language.lans:
  7. print(lan)
  8. # result:
  9. # Python
  10. # C
  11. # Lisp

用魔法函数也可实现上面的功能,而且使用起来会更加简洁。

  1. class Language(object):
  2. # 没错,这也是一个魔法函数,现在先不关注它
  3. def __init__(self, language_list):
  4. self.lans = language_list
  5. # 定义这样一个魔法函数
  6. def __getitem__(self, item):
  7. return self.lans[item]
  8. language = Language(["Python", "C", "Lisp"])
  9. for lan in language:
  10. print(lan)
  11. # result:
  12. # Python
  13. # C
  14. # Lisp

魔法函数对Python的影响

  • 魔法函数不属于定义它的那个类,只是增强了类的一些功能。
  • 实现了特定的魔法函数之后,某些操作会变得特别简单。
  • 我们可以采用实现魔法函数来灵活地设计我们需要的类。

    常用魔法函数

    后续学习会介绍一部分,这里了解即可。

    非数学运算

    字符串表示

  • __repr__()

  • __str__()

    集合、序列

  • __len__()

  • __getitem__()
  • __setitem__()
  • __delitem__()
  • __contains__()

    迭代相关

  • __iter__()

  • __next__()

    可调用

  • __call__()

    with上下文管理器

  • __enter__()

  • __exit__()

    数值转换

  • __abs__()

  • __bool__()
  • __int__()
  • __float__()
  • __hash__()
  • __index__()

    元类相关

  • __new__()

  • __init__()

    属性相关

  • __getattr__(), __setattr__()

  • __getattribute__(), __setattribute__()
  • __dir__()

    属性描述符

  • __get__(), __set__(), __delete__()

    携程

  • __await__(), __aiter__(), __anext__(), __aenter__(), __aexit__()

    数学运算

    看一个例子就行了,因为:

  • 运算方式复杂

  • 实际应用不多 ```python

    实现一个二维向量的加法计算

    class Vector(object): def init(self, x, y):

    1. self.x = x
    2. self.y = y

    def add(self, v):

    1. res_v = Vector(self.x + v.x, self.y + v.y)
    2. return res_v

    def str(self):

    1. return "x: {0}, y: {1}".format(self.x, self.y)

first_vector = Vector(1, 2) second_vector = Vector(3, 4) print(first_vector + second_vector)

result:

x: 4, y: 6

```

以len()为例

引言

  • len()函数可以返回一个序列的长度
  • 首先该类型要定义了__len__()方法

    原理

    当我们使用len()函数获取一些内置对象(list, tuple, set…)的长度时,性能会非常高,因为这些内置对象使用C语言实现的,同时该方法并未对内置对象进行遍历获得长度,而是内置对象维护了一个长度属性,调用方法后,直接进行属性值的读取即可。

    结论

  • 某些方法并未我们想象中的那么简单,内部实现时会做很多优化。

  • 尽量使用Python的内置对象,和内置的一些函数,提高效率。

    小结

    魔法函数使得自定义的类型会具有神奇的功能,让我们可以设计更加灵活的类型,它将我们自定义的类型和一些内建类型建立起了关联,明白了更加底层的一些细节,为后面的的深入学习做了一个铺垫。