Skip to main content
 首页 » 编程设计

python之鸭子类型(duck typing)与基于类的继承

2025年05月04日15grandyang

使用 DuckTyping 方法,下面是两个类 Duck 和 Person,

class Duck: 
   def quack(self): 
       print('Quack') 
 
   def fly(self): 
       print('Flap') 
 
class Person: 
   def quack(self): 
       print('I\'m quacking like a duck') 
 
   def walk(self): 
       print('Walk') 
 
def quackFlap(creature): 
    try:  
       creature.quack() 
    except: # EAFP 
       print('Cannot quack') 
 
    try: 
       creature.flap() # Using hasattr() will violate EAFP 
    except: # EAFP 
       print('Cannot flap')  
 
donald = Duck() 
quackFlap(donald) 
 
p = Person() 
quackFlap(p)  # Duck Typing approach says, Person is not Duck. 

使用基于类的继承方法,下面是两个类 Bird & Duck,

class Bird(object): 
   def quack(self): 
       print('Quack') 
 
   def fly(self): 
       print('Fly') 
 
class Duck(Bird): 
   def quack(self): 
       print('I\'m quacking like a duck') 
   def fly(self): 
       print('Flap') 
 
def quackFlap(creature): 
    if isinstance(creature, Bird): 
       creature.quack() 
       creature.flap() 
 
b = Bird() 
quackFlap(b) 
 
d = Duck() 
quackFlap(d) # Inheritance allowed isinstance() check - Error handling 

问题:

1) DuckTyping 是否避免了子类化?因为在子类化时,我们看不到 DuckTyping 方法的必要性

2) DuckTyping 何时优于基于类的继承?

请您参考如下方法:

1) Does DuckTyping avoid Subclassing? because on subclassing, we do not the necessity of DuckTyping approach

完全没有。当您需要访问父类(super class)上未定义的内容时,鸭子类型(duck typing)只会将不必要的强制转换/检查转换为子类类型。但是通过良好的设计和正确使用多态性,您可以避免这样做(使用 instanceof + cast 来访问子类的特殊性)。

2) When DuckTyping is better than class based inheritance?

这真的取决于......当类之间没有“IS A”关系时,应该避免继承,主要是当它仅用作重新利用代码的手段时。如果存在“IS A”关系,并且代码依赖于“instanceof”的使用,则表明设计不当,即未正确使用多态性。

例如,鸭子类型(duck typing)是一种无需依赖抽象类/接口(interface)(如 Java)即可拥有多态代码的简便方法。但是抽象类/接口(interface)定义了一个契约。使用鸭子类型(duck typing),由于缺乏正式关系,您可以在代码中引入细微的错误。如果你的“庸医”根本不是“庸医”,你就有麻烦了。通过继承,由于子类化抽象类的契约性质,这种情况不太可能发生。