Python进阶:实例讲解Python中的魔法函数(Magic Methods)

webnexus 7年前
   <p><img src="https://simg.open-open.com/show/dce355356c150f3f3760fda198debd73.jpg"></p>    <h2>什么是魔法函数?</h2>    <p>所谓魔法函数(Magic Methods),是Python的一种高级语法,允许你在类中自定义函数(函数名格式一般为__xx__),并绑定到类的特殊方法中。比如在类A中自定义__str__()函数,则在调用str(A())时,会自动调用__str__()函数,并返回相应的结果。在我们平时的使用中,可能经常使用__init__函数和__del__函数,其实这也是魔法函数的一种。</p>    <h2>魔法函数有什么作用?</h2>    <p>魔法函数可以为你写的类增加一些额外功能,方便使用者理解。举个简单的例子,我们定义一个“人”的类People,当中有属性姓名name、年龄age。让你需要利用sorted函数对一个People的数组进行排序,排序规则是按照name和age同时排序,即name不同时比较name,相同时比较age。由于People类本身不具有比较功能,所以需要自定义,你可以这么定义People类:</p>    <pre>  <code class="language-python">class People(object):      def __init__(self, name, age):          self.name = name          self.age = age          return        def __str__(self):          return self.name + ":" + str(self.age)        def __lt__(self, other):          return self.name < other.name if self.name != other.name else self.age < other.age    print("\t".join([str(item) for item in sorted([People("abc", 18), People("abe", 19), People("abe", 12), People("abc", 17)])]))</code></pre>    <p>上个例子中的__lt__函数即less than函数,即当比较两个People实例时自动调用。</p>    <p>再举个例子,实现一个可以任意深度赋值的字典类,如a[0] = 'value1'; a[1][2] = 'value2'; a[3][4][5] = 'value3'。这个和Python自带的defaultdict还有些区别。简单分析一下这个题目:普通的dict可以实现a[0]赋值,但是无法给a[1][2]直接赋值;后者赋值的过程大概为a.get(1).set(2, value),但我们不确定a[1]是否存在,所以很自然会想到要改写dict类中的__getitem__()函数,当a[1]不存在时,声明一个dict,并赋值给a[1]。代码如下:</p>    <pre>  <code class="language-python">class MyDict(dict):      def __setitem__(self, key, value):  # 该函数不做改动,只是为了输出          print("setitem:", key, value, self)          super().__setitem__(key, value)          return        def __getitem__(self, item):                # 主要技巧在该函数          print("getitem:", item, self)          # 基本思路: a[1][2]赋值时 需要先取出a[1] 然后给a[1]的[2]赋值          if item not in self:                    # 如果a[1]不存在              temp = MyDict()                     # 则需要新建一个dict              super().__setitem__(item, temp)     # 并使得a[1] = dict              return temp                         # 返回a[1] 使得a[1][2] = value有效          return super().__getitem__(item)        # 如果a[1]存在 则直接返回a[1]    # 使用例子:  test = MyDict()  test[0] = 'test'  test[1][2] = 'test1'  test[3][4][5] = 'test2'</code></pre>    <h2>Python中有哪些魔法函数?</h2>    <p>Python中每个魔法函数都对应了一个Python内置函数或操作,比如__str__对应str函数,__lt__对应小于号<等。Python中的魔法函数可以大概分为以下几类:</p>    <p>类的构造、删除:</p>    <pre>  <code class="language-python">object.__new__(self, ...)  object.__init__(self, ...)  object.__del__(self)</code></pre>    <p>二元操作符:</p>    <pre>  <code class="language-python">+ object.__add__(self, other)  - object.__sub__(self, other)  * object.__mul__(self, other)  // object.__floordiv__(self, other)  / object.__div__(self, other)  % object.__mod__(self, other)  ** object.__pow__(self, other[, modulo])  << object.__lshift__(self, other)  >> object.__rshift__(self, other)  & object.__and__(self, other)  ^ object.__xor__(self, other)  | object.__or__(self, other)</code></pre>    <p>扩展二元操作符:</p>    <pre>  <code class="language-python">+= object.__iadd__(self, other)  -= object.__isub__(self, other)  *= object.__imul__(self, other)  /= object.__idiv__(self, other)  //= object.__ifloordiv__(self, other)  %= object.__imod__(self, other)  **= object.__ipow__(self, other[, modulo])  <<= object.__ilshift__(self, other)  >>= object.__irshift__(self, other)  &= object.__iand__(self, other)  ^= object.__ixor__(self, other)  |= object.__ior__(self, other)</code></pre>    <p>一元操作符:</p>    <pre>  <code class="language-python">- object.__neg__(self)  + object.__pos__(self)  abs() object.__abs__(self)  ~ object.__invert__(self)  complex() object.__complex__(self)  int() object.__int__(self)  long() object.__long__(self)  float() object.__float__(self)  oct() object.__oct__(self)  hex() object.__hex__(self)  round() object.__round__(self, n)  floor() object__floor__(self)  ceil() object.__ceil__(self)  trunc() object.__trunc__(self)</code></pre>    <p>比较函数:</p>    <pre>  <code class="language-python">< object.__lt__(self, other)  <= object.__le__(self, other)  == object.__eq__(self, other)  != object.__ne__(self, other)  >= object.__ge__(self, other)  > object.__gt__(self, other)</code></pre>    <p>类的表示、输出:</p>    <pre>  <code class="language-python">str() object.__str__(self)   repr() object.__repr__(self)  len() object.__len__(self)  hash() object.__hash__(self)   bool() object.__nonzero__(self)   dir() object.__dir__(self)  sys.getsizeof() object.__sizeof__(self)</code></pre>    <p>类容器:</p>    <pre>  <code class="language-python">len() object.__len__(self)  self[key] object.__getitem__(self, key)  self[key] = value object.__setitem__(self, key, value)  del[key] object.__delitem__(self, key)  iter() object.__iter__(self)  reversed() object.__reversed__(self)  in操作 object.__contains__(self, item)  字典key不存在时 object.__missing__(self, key)</code></pre>    <p> </p>    <p> </p>    <p>来自:https://zhuanlan.zhihu.com/p/24567545</p>    <p> </p>