写在之前
我们在之前说过,「封装」「继承」 和「多态」是 OOP 的重要特征,前面我们已经讲过了继承,今天我们来学习的是 “多态”。这里更多的是针对初学 Python 的读者谈谈如何去理解 “多态”,因为「多态」就如同它的名字一样,在理解上也是「多态」的,算是各有千秋。建议各位在看完本篇文章以后,也要多 Google 一下相关的内容再加深理解。
多态
首先让我们来看一个例子:
>>> 'my name is rocky'.count('m')
2
>>> [1,2,3,4,5,3].count(3)
2
上述例子中 count() 的作用是计数,数数某个元素在对象中出现的次数。在上面的例子里我们并没有限定参数的类型,类似的例子还有:
>>> f = lambda x,y:x+y
还记得上面的上面的 lambda 函数吗?不记得的请看Python拓展之特殊函数。
>>> f('ro','cky')
'rocky'
>>> f(2,3)
5
>>> f(['c','c++'],['java','python'])
['c', 'c++', 'java', 'python']
在上面的例子中我们同样也没有限定参数的类型,当然了也一定不能限制,如果限制的话,那么 Python 就失去了它最舒服的简洁的特性。在使用的时候可以给参数任意适合的类型,总能得到不错的结果。
其实以上就体现了「多态」,即同一种行为具有不同的表现形式和形态的能力,也可以说就是对象多种表现形式的体现。
当然,也有人对此提出了反对意见,因为本质上在参数传入之前,Python 并没有确定参数的类型,所以只能让数据进入函数之后再处理,能处理则最好,不能处理只能罢工报错了。就像下面一样:
>>> f('roc',2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: cannot concatenate 'str' and 'int' objects
对于这种概念之争就比如先有的鸡还是鸡蛋之争,所以我们不来判断哪种对或者哪种错,这个也不是我们本篇文章的重点,在这仅仅是把相关的信息告诉给大家。
「多态」在一些地方也被称为「多型」。我们来看一下权威的《维基百科》中对此的详细解释:
多型(Polymorphism),是指对象导向程式执行时,相同的信息可能会送给多个不同的类别对象,而系统可依据物件所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多型意指相同的信息给予不同的对象会引发不同的动作。
简单的说法就是有多种形式,就算不知道变量或参数所引用的对象类型,也一样可以进行操作,可以说是来着不拒了。就像上面的例子那样。
![](/qrcode.jpg)
再比如,我们之前说过的 repr() 函数,它可以根据输入的任意对象返回一个字符串,这个就是 “多态” 的代表之一。
>>> repr([1,2,3,4,5])
'[1, 2, 3, 4, 5]'
>>> repr(123)
'123'
>>> repr({'name':'rocky'})
"{'name': 'rocky'}"
使用它来实现一个小函数,依然还是多态的代表:
>>> length('what is your name')
the length of 'what is your name' is 17
>>> length([1,2,3])
the length of '[1, 2, 3]' is 3
当然了,多态不是万能的,比如像下面这样做:
>>> length(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in length
TypeError: object of type 'int' has no len()
上面的例子出错了,出错的愿意根据错误提示,明确的告诉我们 “type ‘int’ has no len()”。
上述的种种多态表现,全是因为 Python 是一种不需要预编译的语言,只在运行的时候才确定状态(虽然最终还是编译了)。所以可以这么来说,Python 就被认为天生是一种多态的语言。当然了也有人持有相反的观点,认为 Python 不支持多态,理由也是上面的说法。就比如长跑最后的一公里,有的人想就只剩一公里了,也有的人想竟然还有一公里,是一个道理。
鸭子类型
我们在前面所说的,Python 不检查传入的对象的类型,这种方式通俗的被称为「鸭子类型」,比较高端的方式是叫做「隐式类型」或者「结构式类型」。鸭子类型这个命名源于一句名言:
如果它像鸭子一样走路,像鸭子一样叫,那么它就是一只鸭子。
鸭子类型就意味着可以向任何对象发送任何的消息,语言只关心这个对象能不能接收该消息,不会去强求该对象是否为某一种特定的类型 —— 该对象的多态表现。
写在最后
多态的介绍大概就是这些,对于Python 多态之间的争论我们看看就好,不要太过于在意,我们只要明白了我们该明白的就好。
更多内容,欢迎关注公众号「Python空间」,期待和你的交流。