Fork me on GitHub

Python特殊方法

Python一切皆对象,但同时,Python还是一个多范式语言(multi-paradigm),你不仅可以使用面向对象的方式来编写程序,还可以用面向过程的方式来编写相同功能的程序(还有函数式、声明式等,我们暂不深入)。Python的多范式依赖于Python对象中的特殊方法(special method)。

特殊方法名的前后各有两个下划线。特殊方法又被成为魔法方法(magic method),定义了许多Python语法和表达方式,正如我们在下面的例子中将要看到的。当对象中定义了特殊方法的时候,Python也会对它们有“特殊优待”。比如定义了__init__()方法的类,会在创建对象的时候自动执行__init__()方法中的操作。

可以通过dir()来查看对象所拥有的特殊方法,比如dir(1),我们把1看作是一个整数类的实例,执行dir(1)就是查看1这个整数对象拥有的特殊方法。

运算符

Python中的运算符是通过调用对象的特殊方法来实现的,举一个最常见的例子1+1,实际上是调用1这个对象的__add__()方法。

比如:

'abc' + 'xyz'        # 连接字符串

实际上是执行了下述操作:

'abc.__add__('xyz')'

所以在python中看两个对象能否进行加法运算,首先要看相应的对象是否有__add__()方法。一旦对象有__add__()方法,即使这个对象从数学上来说不可加,但是我们仍然可以用加法的形式(+运算符)来表达object.__add__()方法,这有点类似C#中的运算符重载,在Python中,运算符起到简化书写的功能,但它依靠特殊方法实现。

Python不强制用户使用面向对象的编程方法。用户可以选择自己喜欢的使用方式(比如选择使用+符号,还是使用更加面向对象的__add__()方法)。特殊方法写起来总是要更费事一点。

尝试下面的操作,看看效果,在想想这些对象的方法对应的运算符。

(1.8).__mul__(2.0)

(True.__or__(False)

内置函数

与运算符类似,python的内置函数也是调用对象的特殊方法,比如:

abs(-1)                # 求绝对值

实际上是执行了下述操作:

(-1).__abs__()         # 调用-1这个对象的特殊方法来求绝对值。

相对于去调用对象特殊方法,直接使用内置函数显的更加短小简洁,当然,可能看起来没有调用对象的特殊方法那么直观。

序列对象的引用

python中的list,tuple,range这三类都属于序列对象,他们各自有不同的特性,适用于不同的场景,他们有一个共同的特点就是他们的对象都是一个序列,可以简单的理解成是一个数组。

下面是我们一个常见的对一个list对象的引用:

li=[1,2,3,4,5,6,7,8]               # 定义一个从1-8的list对象li
a=li[3]                                  # 变量a指向对象li中的第三个元素的引用

这是一个很常见的引用,就像我们在C#中通过数组下标来访问一个数组成员一样。
在python中,它相当于是调用了li对象的__getitem__()方法来访问list中的成员一样:

li.__getitem__(3)

可以思考一下,这个__getitem__()方法是如何定义的?

函数

在python中,函数也是一种对象。实际上,任何一个有__call__()特殊方法的对象都被当作是函数。比如下面的例子:

class SampleMore(object):     # 定义一个类,其__call__()方法接收一个参数a并返回a+5
        def __call__(self,a):
                return a+5
add = SampleMore()            # 实例化这个类,并用add变量引用这个类的对象。
add(2)                        # 调用这个对象的方法,实际上就是调用__call__()方法
map(add,[2, 4, 5])            # 将add作为函数依次作用到这个list中。

add作为SampleMore类的一个对象,当被当作函数来调用时,add执行加5的操作。add还可以作为函数对象,被传递给map()函数。

总结

对于内置的对象(比如整数、表、字符串等),它们所需要的特殊方法都已经在Python中准备好了。而用户自己定义的对象也可以通过增加特殊方法,来实现自定义的语法。特殊方法比较靠近Python的底层,许多Python功能的实现都要依赖于特殊方法。我们将在以后看到更多的例子。

参考

Python深入01 特殊方法与多范式

0%