欢迎访问Python每天3分钟系列。每天花3分钟时间,学习或温习一个Python知识点。今天是第034篇:

图片

Duck Typing 鸭子类型

Python界有这么一句话:

“只要你走路像鸭子,叫起来像鸭子,我就把你当成鸭子。

这就是传说中的鸭子类型,用来形容Python对待类型的一种态度。它有别于Java等强类型语言。

Java对待类型的态度是:

“你必须是真正的鸭子(或者继承自鸭子),否则就算你走路像鸭子,叫起来像鸭子也不行。

来,上代码!

这是鸭子类,它有两个关键方法:鸭子叫,鸭子步。

class Duck:

 def duck_walk(self):
  print('走?步')

 def duck_sound(self):
  print('嘎嘎嘎')

这是全聚德,一个对鸭子来说很可怕的地方,它有一个静态方法cook用来招待送来的鸭子:

# 全聚德
class QuanJude:

 @staticmethod
 def cook(duck):
  print("-- 鸭子来了,先检查一下 ---")
  # 走走看
  duck.duck_walk()
  # 叫两声听听
  duck.duck_sound()

  print("验证完毕,可以下锅了")

这一直运行良好:

# 搞两只鸭子
d1 = Duck()
d2 = Duck()

# 送到全聚德
QuanJude.cook(d1)
QuanJude.cook(d1)

运行结果:

-- 鸭子来了,先检查一下 ---
走?步
嘎嘎嘎
验证完毕,可以下锅了
-- 鸭子来了,先检查一下 ---
走?步
嘎嘎嘎
验证完毕,可以下锅了

可是有一种,从小就在鸭子群里长大,它们学习能力很强,也学会了鸭子步和鸭子叫:

class Chicken:

 def __init__(self):
  print('我其实是一个小鸡,谁说小鸡不会鸭子叫呢!')

 def duck_walk(self):
  print('走?步')

 def duck_sound(self):
  print('嘎嘎嘎')

有一天,它们也被送到了全聚德。你看多学点东西总是好的,可以去高级餐厅。

# 抓了两只鸡
c1 = Chicken()
c2 = Chicken()

# 送到全聚德
QuanJude.cook(c1)
QuanJude.cook(c1)

运行结果:

我其实是一个小鸡,谁说小鸡不会鸭子叫呢!
我其实是一个小鸡,谁说小鸡不会鸭子叫呢!
-- 鸭子来了,先检查一下 ---
走?步
嘎嘎嘎
验证完毕,可以下锅了
-- 鸭子来了,先检查一下 ---
走?步
嘎嘎嘎
验证完毕,可以下锅了

这说明cook方法根本不在意你是鸭子还是鸡,或者别的。只要你有那两个方法,就把你当成鸭子煮了! 简单粗暴!

这也没什么大不了。烤鸭烤出来一直鸡也还凑合吧。直到有一天…

有些很顽皮的小朋友,他们也学会了鸭子叫,也会走鸭子步:

class NaughtyBoy:

 def __init__(self):
  print('我是顽皮的小朋友,嘻嘻嘻')

 def duck_walk(self):
  print('走?步')

 def duck_sound(self):
  print('嘎嘎嘎')

有一天他不小心,溜溜达达,走到了全聚德的后厨门口。好奇心来了,他们决定进去看看….

总结一下:

  1. Python不在意类型,只要对象具有相应的方法就可以。这就是所谓的鸭子类型! 只要你走路像鸭子,叫起来像鸭子,我就把你当成鸭子。
  2. 鸭子类型的好处是方便,你只要给类加上相应的方法就能用,不一定要继承特定的父类。
  3. 鸭子类型的坏处就是不安全。上面发生的事情,在Java中是绝对不会发生的,因为Java在编译时会首先检查类型是不是Duck。

自我感觉今天的3分钟还比较有意思。麦友小伙伴们,如果你也这么认为,考虑转发一下?谢谢!

声明:本网站资源来源于网络收集,如有侵权,请联系站长进行删除处理。 分享目的仅供大家学习和交流,请不要用于商业用途,否则后果自负。本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解。本站资源售价只是赞助,收取费用仅维持本站的日常运营所需。反馈邮箱:1159995880@qq.com