Python基础教程 多态和方法

7.1.2 多态和方法

你收到一个对象,却根本不知道它是如何实现的——它可能是众多“形态”中的任何一种。你只知道可以询问其价格,但这就够了。至于询问价格的方式,你应该很熟悉。

>>> object.get_price()

2.5

像这样与对象属性相关联的函数称为方法。你在本书前面见过这样的函数:字符串、列表和字典的方法。多态你其实也见过。

>>> 'abc'.count('a')

1

>>> [1, 2, 'a'].count('a')

1

如果有一个变量x,你无需知道它是字符串还是列表就能调用方法count:只要你向这个方法提供一个字符作为参数,它就能正常运行。

下面来做个实验。标准库模块random包含一个名为choice的函数,它从序列中随机选择一个元素。下面使用这个函数给变量提供一个值。

>>> from random import choice

>>> x = choice(['Hello, world!', [1, 2, 'e', 'e', 4]])

执行这些代码后, x可能包含字符串'Hello, world!',也可能包含列表[1, 2, 'e', 'e', 4]。具体是哪一个,你不知道也不关心。你只关心x包含多少个'e',而不管x是字符串还是列表你都能找到答案。为找到答案,可像前面那样调用count。

>>> x.count('e')

2

从上述结果看, x包含的应该是列表。但关键在于你无需执行相关的检查,只要x有一个名为count的方法,它将单个字符作为参数并返回一个整数就行。如果有人创建了包含这个方法的对象,你也可以像使用字符串和列表一样使用这种对象。

多态形式多样

每当无需知道对象是什么样的就能对其执行操作时,都是多态在起作用。这不仅仅适用于方法,我们还通过内置运算符和函数大量使用了多态。请看下面的代码:

>>> 1 + 2

3

>>> 'Fish' + 'license'

'Fishlicense'

上述代码表明,加法运算符(+)既可用于数(这里是整数),也可用于字符串(以及其他类型的序列)。为证明这一点,假设你要创建一个将两个对象相加的add函数,可像下面这样定义它(这与模块operator中的函数add等价,但效率更低):

def add(x, y):

return x + y

可使用众多不同类型的参数来调用这个函数。

>>> add(1, 2)

3

>>> add('Fish', 'license')

'Fishlicense'

这也许有点傻,但重点在于参数可以是任何支持加法的对象①。如果要编写一个函数,通过打印一条消息来指出对象的长度,可以像下面这样做(它对参数的唯一要求是有长度,可对其执行函数len)。

def length_message(x):

print("The length of", repr(x), "is", len(x))

如你所见,这个函数还使用了repr。 repr是多态的集大成者之一,可用于任何对象,下面就来看看:

>>> length_message('Fnord')

The length of 'Fnord' is 5

>>> length_message([1, 2, 3])

The length of [1, 2, 3] is 3

很多函数和运算符都是多态的,你编写的大多数函数也可能如此,即便你不是有意为之。每当你使用多态的函数和运算符时,多态都将发挥作用。事实上,要破坏多态,唯一的办法是使用诸如type、 issubclass等函数显式地执行类型检查,但你应尽可能避免以这种方式破坏多态。重要的是,对象按你希望的那样行事,而非它是否是正确的类型(类)。然而,不要使用类型检查的禁令已不像以前那么严格。引入本章后面将讨论的抽象基类和模块abc后,函数issubclass本身也是多态的了!

注意 这里讨论的多态形式是Python编程方式的核心,有时称为鸭子类型。这个术语源自如下说法:“如果走起来像鸭子,叫起来像鸭子,那么它就是鸭子。 ”有关鸭子类型的详细信息,请参阅http://en.wikipedia.org/wiki/Duck_typing。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181015G0E0Q700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券