关于Python鸭子类型
Python对实现多态性的要求很宽松,这就代表我们可以对不同对象调用同名的操作,甚至不用关注和谐对象的类型是什么,我们称这样的方式叫做鸭子类型。说的再通俗一点,就是如果某个对象的形状像鸭子,走的像鸭子,叫声像鸭子,那么就可以称这个对象是鸭子。当然这是通俗的解释,python中的鸭子类型也是这个道理,我们用实例解释一下。
下面我们定义了一个父类名为Quote
,它含有两个who
和says
方法,以及定义了两个子类QuestionQuote
和ExclamationQuote
,这两个子类中都声明了says
方法,也就是覆盖了父类的says
方法。
class Quote():
def __init__(self, person, words):
self.person = person
self.words = words
def who(self):
return self.person
def says(self):
return self.words + '.'
class QuestionQuote(Quote):
def says(self):
return self.words + '?'
class ExclamationQuote(Quote):
def says(self):
return self.words + '!'
hunter1 = Quote('James', "I'm hunting rabbits")
print(f'{hunter1.who()} says: {hunter1.says()}')
hunter2 = QuestionQuote('Mary', "What's up")
print(f'{hunter2.who()} says: {hunter2.says()}')
hunter3 = QuestionQuote('Tom', "It's rabbit season")
print(f'{hunter3.who()} says: {hunter3.says()}')
# 输出内容:
# James says: I'm hunting rabbits.
# Mary says: What's up?
# Tom says: It's rabbit season?
上述例子其实是一个很简单的继承关系,声明了不同对象实例,分别都调用各自方法输出各自方法定义的内容,除了没有被覆盖的word
方法任沿用于父类。
我们继续定义一个BabblingBrook
类,它也包含两个方法who
和says
,这里的方法其实和上面那个例子里的who
和says
没有任何关系,只是同名而已。紧接着可以看到我们又一定了一个公共的who_says(obj)
函数,然后我们调用它并把所有例子中生成的实例对象传递给who_says(obj)
函数的obj变量,代码最后部分,你可以看到对不同对象执行who()
和says()
方法都是可以的,而且都返回了各自方法所定义的实际内容。
class BabblingBrook():
def who(self):
return 'Brook'
def says(self):
return 'Babble'
brook = BabblingBrook()
def who_says(obj):
print(f'{obj.who()} says: {obj.says()}')
who_says(hunter1)
who_says(hunter2)
who_says(hunter3)
who_says(brook)
# 输出内容:
# James says: I'm hunting rabbits.
# Mary says: What's up?
# Tom says: It's rabbit season?
# Brook says: Babble
这就是我们说的鸭子类型,不用管对象本身是谁,都可以调用同名方法,只要对象有这个方法就行。(反过来说就是只要有这个行为,样子,我们认为它就是只鸭子。)