• Python进阶


    一、什么是特殊方法?

    特殊方法可以理解为在调用内置方法时,程序背后真正被调用的方法,通常以双下划线开头和结尾,例如 __len__,有些地方也称其为"魔术方法"(Magic Method)。
    比如,我们比较两个数的大小时,一般都会使用大于号或小于号进行判断:

    # 命令行调用
    >>> 1 < 2
    True
    

    实际上是在调用 __lt__() 方法:

    # 命令行调用
    >>> int.__lt__(1, 2)
    True
    

    二、特殊方法有什么用?

    既然程序都已经自动调用了,那它有什么用呢?其实,它更多的用于我们自己编写的类中。下面我们自行编写一个向量类:

    class Vector:
       def __init__(self, x=0, y=0):
           self.x = x  # x坐标
           self.y = y  # y坐标
    

    我们在创建好两个向量实例后,发现单独显示的貌似时地址,将两个向量相加时也直接报错了,跟我们预想的完全不一样:

    # 命令行调用
    >>> v1 = Vector(1, 1)
    >>> v1
    <__main__.Vector object at 0x0000013C5E4CC9D0>
    >>> v2 = Vector(2, 3)
    >>> v2
    <__main__.Vector object at 0x0000013C5E4CC8B0>
    >>> v1 + v2
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
    >>>
    

    这时候特殊方法就派上用场了。下面通过完善这个向量类,介绍几款常用的特殊方法。 

    三、几款常用的特殊方法

    __repr__() 这个方法的主要作用是将一个对象用字符串的形式输出,便于我们进行辨认。
    对于我们这个向量类,我们想让每个向量实例都输出成“Vector(m, n)”这样的格式,所以我们就可以使用 __repr__() 方法进行定义:

    class Vector:
        def __init__(self, x=0, y=0): 
            self.x = x
            self.y = y
        def __repr__(self):
            # 定义Vector类的对象的字符串返回格式
            return 'Vector({}, {})'.format(self.x, self.y)
    
    # 输出结果
    >>> v1 = Vector(1, 1)
    >>> v1
    Vector(1, 1)
    

    可以看到,输出的结果符合我们的预期。我们继续通过几个特殊方法来完成向量的模、加法以及数乘等操作:

    from math import hypot
    
    class Vector:
        def __init__(self, x=0, y=0): 
            self.x = x
            self.y = y
        def __repr__(self):
            # 定义Vector类的对象的字符串返回格式
            return 'Vector({}, {})'.format(self.x, self.y)
        def __abs__(self):
            # 通过计算x,y坐标的欧几里得距离,返回向量的模
            return hypot(self.x, self.y)
        def __bool__(self):
            # 判断向量的模是否为0,从而进行布尔运算
            return bool(abs(self))
        def __add__(self, other):
            # 定义两个向量的加法
            x = self.x + other.x
            y = self.y + other.y
            return Vector(x, y)
        def __mul__(self, scalar):
            # 定义一个数scalar与向量的乘积
            return Vector(self.x * scalar, self.y * scalar)
    
    # 命令行调用
    >>> v1 = Vector(1, 2)    # 定义向量v1的坐标为(1, 2)
    >>> v2 = Vector(2, 2)    # 定义向量v2的坐标为(2, 2)
    >>> v1
    Vector(1, 2)
    >>> v2
    Vector(2, 2)
    >>> v1 + v2    # 向量相加
    Vector(3, 4)
    >>> v1 * 3      # 向量的数乘
    Vector(3, 6)
    >>> abs(v1 + v2)    # 求 v1 + v2 的模
    5.0
    >>> bool(v1)    # 对向量v1进行布尔运算True
    >>> bool(Vector(0, 0))    # 对向量(0, 0)进行布尔运算
    False
    

    通过对一系列特殊方法进行定义,我们基本上完成了向量的基本操作。这让我们这个Vector类变得生动起来。 

    四、特殊方法的意义

    通过在自定义的类中重写一些原生类方法背后的特殊方法,可以使得自定义的类也拥有和原生类相同的访问、操作方式,让使用者尽量不会感受到自定义类与原生类的差异,从而保持语言上的一致性。

    五、如何查找特殊方法?

    通过Python语言参考手册的“Data Model”,可以查找到83个特殊方法的名字,其中47个用于实现算术运算、位运算和比较操作。



    注:文章内容出自《流畅的Python》第一章

  • 相关阅读:
    Jetty 入门
    Spring MVC 学习 之
    Spring MVC 学习 之
    Spring MVC 学习 之
    call apply 使用
    maven学习系列 之 常见问题
    SQL Server数据库partition by 与ROW_NUMBER()函数使用详解[转]
    .NET 同步 异步 委托
    常用JS方法
    通过 NPOI 生成 Excel
  • 原文地址:https://www.cnblogs.com/dev-liu/p/python_magic_method.html
Copyright © 2020-2023  润新知