Duck typing
Python не проверяет, от какого класса унаследован объект — только то, есть ли у него нужный метод.
«Если это выглядит как утка и крякает как утка...»
В разделе 14.18 все классы разделяли общего родителя не всегда. На самом деле Python вообще не проверяет, от какого класса объект унаследован, чтобы вызвать метод — важно только, ЕСТЬ ли у объекта нужный метод:
class Sobaka: # никак не связана с Robot
def predstavitsya(self):
print("Гав! Я собака.")
class Robot: # никак не связана с Sobaka
def predstavitsya(self):
print("БИП. Я робот.")
def poznakomit(obj):
obj.predstavitsya() # неважно, какого obj класса — важно, что метод есть
poznakomit(Sobaka())
poznakomit(Robot())
Sobaka и Robot НЕ имеют общего родителя (кроме неявного object), но poznakomit() одинаково успешно работает с обоими. В Python интерфейс — это фактическое наличие нужного метода, а не формальная запись в дереве наследования.Название пришло из выражения «если оно выглядит как утка, плавает как утка и крякает как утка — вероятно, это и есть утка»: неважно, как объект был создан, важно, что он УМЕЕТ.
zhivotnye = [Sobaka(), Robot(), "просто строка"]
for zh in zhivotnye:
zh.predstavitsya()
Гав! Я собака.
БИП. Я робот.
Traceback (most recent call last):
AttributeError: 'str' object has no attribute 'predstavitsya'
Duck typing не проверяет наличие метода заранее — Python просто пытается вызвать predstavitsya() и падает в момент вызова, если метода нет. Гибкость duck typing не отменяет ответственность: класть в один список объекты, которые ДОЛЖНЫ поддерживать общий метод, нужно осознанно.
for zh in zhivotnye:
if hasattr(zh, "predstavitsya"):
zh.predstavitsya()