Duck Typing

A humorous and apt representation of duck typing. Source: Mastracci, 2014.
A humorous and apt representation of duck typing. Source: Mastracci, 2014.

Duck Typing is a way of programming in which an object passed into a function or method supports all method signatures and attributes expected of that object at run time. The object's type itself is not important. Rather, the object should support all methods/attributes called on it. For this reason, duck typing is sometimes seen as "a way of thinking rather than a type system".

In duck typing, we don't declare the argument types in function prototypes or methods. This implies that compilers can't do type checking. What really matters is if the object has the particular methods/attributes at run time. Duck typing is therefore often supported by dynamic languages. However, some static languages are beginning to "mimic" it via structural typing.

Discussion

  • What's the origin of the phrase "duck typing"?

    The phrase originates from an old saying,

    If it walks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

    What does this mean? Even a non-duck entity that behaves like a duck can be considered a duck because emphasis is on behaviour. By analogy, for computing languages, the type of an object is not important so long as it behaves as expected. This behaviour is defined by the object's methods/properties/attributes while expectations are set by those who invoke the methods/properties/attributes.

    For example, a Book class is expected to have an attribute numPages and a method getPage(number), where number is an integer. Let's say a function searchPhrase(book, phrase) is meant to search for a given phrase in a book. This function calls book.getPage() for all book.numPages of the book. A Newspaper is obviously not a book but with duck typing this doesn't matter. If Newspaper has implemented numPages and getPage(number), it can be passed into searchPhrase(book, phrase) as if it's a book. Though it's not a book, it's sufficient that it behaves like one within the context of searchPhrase.

  • What's the advantage of having duck typing?
    Duck typing is more about convenience than type safety. Source: Cui, 2015.
    Duck typing is more about convenience than type safety. Source: Cui, 2015.

    It's been said that dynamic typing in general cuts down development time. There's less boilerplate code. Code is easier to hack. With static typing, compile-time checks slow down the development process. Static typing could be used at a later point to get better performance. Others recommend duck typing only for prototyping and never for production.

    While it's true that compile-time checks are useful to catch potential problems early, duck typing enforces following coding conventions, documentation and test-driven methodologies.

    Since duck typing isn't exactly a type system, it gives programmers flexibility. In Python, for example, common things are simpler to code. While static typed languages use interfaces, such interfaces may involve excessive refactoring of client code.

  • Isn't duck typing more like late binding than a type system?

    It can be argued that duck typing is not really a type system in the sense of run-time or compile-time type systems. Type systems typically prescribe rules for defining types, for deducing types from expressions, for determining legality of expressions or storage based on types, and so on. Duck typing doesn't do any of these. Joe Esposito has commented that, "Duck typing is based around conventions, written in the docs instead of code. This allows the language to defer the type system".

    Late binding is when an object or method is bound to a name at run time. Duck typing looks similar to late binding except for a subtle difference that it's based on behaviour rather than declared type.

    One way to understand this is to recognize that C# (a static typed language) allows for method overloading where methods differ only by their arguments types. This is not possible in Python (dynamic typed language) but duck typing fills in since run-time behaviour is emphasized rather than the type of the object passed to the method. Also, because it's interpreted and does late binding, duck typing is easy to do.

  • Can you compare duck typing with structural typing?
    Example of structural typing in Scala. Source: Underwood, 2017, slide 42.
    Example of structural typing in Scala. Source: Underwood, 2017, slide 42.

    Joe Esposito makes a distinction between static duck typing and dynamic duck typing. With the latter, compile-time checks are skipped and this is what we mean when we refer to duck typing. Static duck typing is similar to structural typing that some static typed languages (Scala, F#) support. Structural typing allows for some compile-time checks, not on types but on the supported methods/attributes. Structural typing may be seen as a compiler-enforced subset of duck typing. However, we should also note that structural typing is essentially static typing while duck typing is dynamic.

    Just as duck typing is for dynamic typed languages, so is structural typing for static typed languages. Erlang's Behaviours can be seen as static duck typing, that is, with compile-time checking.

    Among the languages that support structural typing are Scala, OCaml, Go, Elm and PureScript.

  • Can we say that duck typing is another name for implied interfaces?

    Static typed languages use explicit interfaces. In C#, we use interfaces: any type that implements an interface can be passed into a method/function that accepts that interface. This was how flexibilty was built into static typed languages but this required upfront interface declaration.

    Python doesn't have explicit interfaces: interfaces are implied. For Python, this is not different from duck typing. However, implied interfaces are supported by C++ (for example) in its STL library. Given that C++ does compile-time checks, we can't say in general that implied interfaces is the same as duck typing. Note that when interfaces are implied, there's no formal interface definition, and at best, it may be a shared documentation.

  • What is goose typing?
    An example of goose typing in Python. Source: Kim 2017.
    An example of goose typing in Python. Source: Kim 2017.

    In Python, duck typing is an implied or informal interface. This is sometimes called a protocol. For instance, any class or object that implements __len__ and __getitem__ is said to conform to the sequence protocol. Therefore, it can be accessed as if it's a sequence. The sequence can be indexed or sliced.

    With goose typing, the interface or protocol is made explicit. This is done using an Abstract Base Class (ABC). In the call isinstance(obj, cls), the second argument must be an ABC. The ABC class itself can't be instantiated but another class provides an implementation of the expected interfaces. However, this other class is simply registered (via a decorator) as conforming to the ABC's interface; that is, it's not explicitly derived from the ABC. For this reason, we call goose typing as "virtual subclassing of Python ABCs."

    Among the languages supporting goose typing are Python, TypeScript and Go.

  • What languages support duck typing?
    • Python and Ruby support duck typing, both of which are dynamic typed languages. In general, dynamic typed languages such as JavaScript and TypeScript support duck typing. While C# doesn't, some parts of .NET use duck typing.
    • In Ruby, for example, StringIO doesn't have IO in its class hierarchy. Yet, it behaves like an IO due to duck typing. In fact, we may say that StringIO and IO share a common protocol, which is exactly how the duck typing concept is seen in OOP languages such as Smalltalk and ObjectiveC. This can be said of Python as well. For example, an iterable is one that supports the iterator protocol, which is nothing more than implementing necessary methods for an object.
    • In PHP, PHP's dynamic typing system and object-oriented features enable duck typing to a certain extent.
  • How is duck typing related to LBYL and EAFP?
    Duck typing and EAFP. Source: Schafer, 2016.

    LBYL expands to Look Before You Leap while EAFP expands to Easy to Ask for Forgiveness than Permission. Both these concepts are typically discussed in Python (and possibly other languages as well). Python prefers the EAFP approach, which is the opposite of LBYL.

    With LBYL, we typically check if an object is of a compatible type before performing operations on it, such as calling its method. Python has a built-in function isinstance() to do this. With EAFP, we simply call the object's method, expecting that method to be present. If it's not, an exception will be thrown by the Python interpreter, which the code is expected to handle.

    With duck typing, validating an object's type is not Pythonic. Thus, duck typing plays well with Python's preference for EAFP though the use of hasattr() can be used instead.

Milestones

1946

Emil Mazey states at a meeting that "I can’t prove you are a Communist. But when I see a bird that quacks like a duck, walks like a duck, has feathers and webbed feet and associates with ducks—I’m certainly going to assume that he is a duck." The phrase might have originated earlier from James Whitcomb Riley (1849–1916).

1980

Languages of the 1980s such as Smalltalk-80 and Objective-C have the concept of protocols, where the interface is more relevant than the class. In 1992, with reference to Smalltalk-80, William R. Cook of Apple Computer states that interface hierarchy is more useful that inheritance hierarchy.

Jul
2000

What may be the one of the earliest use of the term "duck typing" among programmers, Alex Martelli discusses it on the comp.lang.python Google Group as an alternative to method overloading of C++. He states that duck typing is closer in spirit to polymorphism of C++. He clarifies,

You don't really care for IS-A -- you really only care for BEHAVES-LIKE-A-(in-this-specific-context), so, if you do test, this behaviour is what you should be testing for.
2015
Four approaches to typing in Python. Source: Ramalho 2020.
Four approaches to typing in Python. Source: Ramalho 2020.

Alex Martelli coins the term goose typing in the first edition of his book titled Fluent Python.

Mar
2017

PEP 544 proposes to introduce structural subtyping to Python. This is subsequently accepted into Python 3.8 (October 2019).

Sample Code

  • # Source: Wikipedia, 2017.
     
    class Sparrow:
        def fly(self):
            print("Sparrow flying")
     
    class Airplane:
        def fly(self):
            print("Airplane flying")
     
    class Whale:
        def swim(self):
            print("Whale swimming")
     
    # The type of entity is not specified
    # We expect entity to have a callable named fly at run time
    def lift_off(entity):
        entity.fly()
     
    sparrow = Sparrow()
    airplane = Airplane()
    whale = Whale()
     
    lift_off(sparrow) # prints `Sparrow flying`
    lift_off(airplane) # prints `Airplane flying`
    lift_off(whale) # Throws the error `'Whale' object has no attribute 'fly'`
     

References

  1. Adamko, Martin. 2022. "Duck Types for PHP." Github, January 17. Accessed 2022-01-17.
  2. Atten, John. 2014. "Is Duck Typing a Type System, or a Way of Thinking?" January 4. Accessed 2017-12-28.
  3. Beust, Cedric. 2005. "The Perils of Duck Typing." Otaku. April 15. Accessed 2017-12-28.
  4. C2 Wiki. 2013. "Walks Likea Duck." Cunningham & Cunningham. June 14. Accessed 2017-12-28.
  5. C2 Wiki. 2014. "Duck Typing." Cunningham & Cunningham. January 7. Accessed 2017-12-28.
  6. Cannon, Brett. 2016. "Idiomatic Python: EAFP versus LBYL." MSDN blog. June 29. Accessed 2020-05-27.
  7. Cook, William R. 1992. "Interfaces and specifications for the Smalltalk-80 collection classes." Proceeding OOPSLA '92 conference proceedings on Object-oriented programming systems, languages, and applications, Vancouver, British Columbia, Canada, October 18-22, pp. 1-15. Accessed 2018-08-28.
  8. Cui, Yan. 2015. "Why I like Go’s interfaces." The Burning Monk. May 11. Accessed 2017-12-29.
  9. Foord, Michael. 2011. "Duck Typing in Python: What Type is My Data?" Voidspace. August 2. Accessed 2017-12-28.
  10. Haack, Phil. 2014. "Duck Typing Is More Than Quackery". Haacked. January 4. Accessed 2017-12-28.
  11. Hettinger, Raymond (ed). 2019. "What’s New In Python 3.8." Release 3.8, October 14. Accessed 2021-11-23.
  12. Janmyr, Anders. 2010. "Static Typing." Jayaway blog. April 14. Accessed 2017-12-28.
  13. Kim, Don. 2017. "Duck Typing vs. Goose Typing, Pythonic Interfaces." Blog, tl;dr, July 17. Accessed 2021-12-15.
  14. Langa, Łukasz. 2018. "PEP 569 -- Python 3.8 Release Schedule." Python Developer's Guide, January 27. Accessed 2021-12-15.
  15. Levkivskyi, Ivan, Jukka Lehtosalo, and Łukasz Langa. 2017. "PEP 544 -- Protocols: Structural subtyping (static duck typing)." Python Developer's Guide. March 5. Accessed 2017-12-29.
  16. Lippert, Eric. 2014. "What is duck typing?" Blog: Fabulous adventures in coding. January 2. Accessed 2017-12-28.
  17. Martelli, Alex. 2000. "polymorphism (was Re: Type checking in python?)." comp.lang.python, Google Groups, July 26. Accessed 2018-08-28.
  18. Mastracci, Matt. 2014. "Succinct and accurate." Twitter. November 23. Accessed 2017-12-29.
  19. Mikera. 2011. "What is the supposed productivity gain of dynamic typing?" StackExchange. November 29. Accessed 2017-12-28.
  20. Programiz. 2017. "Python Iterators." Accessed 2017-12-28. Accessed 2017-12-28.
  21. Python Docs. 2017. "Glossary." V3.6.4. Python Software Foundation. October 4. Accessed 2017-12-11.
  22. Ramalho, Luciano. 2015. "goose typing is a new term coined by..." Tweet, on Twitter, January 28. Accessed 2021-12-15.
  23. Ramalho, Luciano. 2020. "Overview of the 4 approaches to typing available in modern #Python." Tweet, on Twitter, October 15. Accessed 2021-12-15.
  24. Reigel, Alexis. 2012. "Static vs dynamic vs strong vs weak vs duck typing." March 19. Accessed 2017-12-28.
  25. Ronacher, Armin. 2014. "Revenge of the Types." Thoughts and Writings. August 24. Accessed 2017-12-28.
  26. Schafer, Corey. 2016. "Python Tutorial: Duck Typing and Asking Forgiveness, Not Permission (EAFP)." YouTube. February 9. Accessed 2017-12-28.
  27. Schuster, Werner. 2007. "Duck Typing and Protocols vs. Inheritance." InfoQ. November 30. Accessed 2017-12-28.
  28. Shannon, Mark. 2021. "[Python-Dev] Re: Keeping Python a Duck Typed Language." Python Mailing List, April 21. Accessed 2021-12-15.
  29. Shindich, Alex, and Curt Hagenlocher. 2001. "Implied Interface." Shindich.com. November 30. Accessed 2017-12-28.
  30. Sirkovský, Marek. 2016. "Duck typing in C#." Medium, October 31. Accessed 2018-08-28.
  31. Sitaker, Kragen Javier. 2002. "isinstance() considered harmful." The Canonical Hackers. March 1. Updated 2016-11-30. Accessed 2017-12-28.
  32. Telastyn. 2014. "How can a statically typed language support duck typing?" StackExchange. August 11. Accessed 2017-12-28
  33. Underwood, Tim. 2017. "A Brief Intro to Scala." SlidePlayer. Accessed 2017-12-29.
  34. Wikipedia. 2017. "Duck typing." December 25. Accessed 2017-12-28.
  35. Wikipedia. 2018. "Duck test." August 25. Accessed 2018-08-28.

Further Reading

  1. Atten, John. 2014. "Is Duck Typing a Type System, or a Way of Thinking?" January 4. Accessed 2017-12-28.
  2. Block, Glenn. 2014. "On Duck Typing." Code Better. January 5. Accessed 2017-12-28.
  3. Scarioni, Carlo. 2013. "Duck Typing in Scala: Structural Typing." DZone. February 20. Accessed 2017-12-28.
  4. Brown, Gregory. 2010a. "Duck Typing in Practice, Part 1." Practicing Ruby. December 28. Accessed 2017-12-28.
  5. Brown, Gregory. 2010b. "Duck Typing in Practice, Part 2." Practicing Ruby. December 31. Accessed 2017-12-28.
  6. Zemek, Paulo. 2010. "DynamicObjects – Duck-Typing in .NET." Code Project. November 5. Accessed 2017-12-28.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
3
1
6683
4
1
558
1
3
67
1645
Words
24
Likes
78K
Hits

Cite As

Devopedia. 2024. "Duck Typing." Version 9, June 10. Accessed 2024-06-25. https://devopedia.org/duck-typing
Contributed by
4 authors


Last updated on
2024-06-10 03:27:48