Python Duck Typing

Duck Typing is a concept where type of the object is not important as compared to the methods it declared or defined, when we call a method irrespective of its class called as a Duck Typing.

Duck Typing

We know that in Python, the data type of the variables is not explicitly declared. This does not mean that Python variables do not have a type.

Every variable or object in Python has a type and the type is implicitly assigned depending on the purpose for which the variable is used.

CopiedCopy Code
		
x = 5 #store integer into x 
print(type(x)) #display type of x class 'int'
x = 'Hello' #store string into x 
print(type(x)) #display type of x class 'str'

Python variables are names or tags that point to memory locations where data is stored. They are not worried about which data we are going to store. So, if 'x' is a variable, we can make it refer to an integer or a string as shown in the previous examples. We can conclude two points from this discussion:

  1. Python's type system is 'strong' because every variable or object has a type that we can check with the type() function.
  2. Python's type system is 'dynamic' since the type of a variable is not explicitly declared, but it changes with the content being stored.

Similarly, if we want to call a method on an object, we do not need to check the type of the object and we do not need to check whether that method really belongs to that object or not. For example, take a method call_talk() that accepts an object (or instance).

def call_talk(obj):

obj.talk()

The call_talk() method is receiving an object 'obj' from outside and using this object, it is invoking (or calling) talk() method.

Duck Typing Examples:

CopiedCopy Code
 
class Duck: #duck typing example
   def talk(self): 
      print('Quack, quack!') #Duck class contains talk() method 
#Human class contains talk() method 
class Human: 
   def talk(self): 
      print('Hello, hi!')
def call_talk(obj): 
      obj.talk() 
x = Duck()
call_talk(x) 
x = Human() 
call_talk(x)
CopiedCopy Code

class Dog: 
   def bark(self): 
      print('Bow, bow!') 
class Duck: 
   def talk(self): 
      print('Quack, quack!') 
class Human: 
   def talk(self): 
      print('Hello, hi!') 
def call_talk(obj): 
   obj.talk() 
x = Duck() 
call_talk(x)
x = Human() 
call_talk(x) 
x = Dog() 
call_talk(x)  #ERROR occurs in this call

So in Python, we never worry about the type (class) of objects. The object type is distinguished only at runtime. If 'it walks like a duck and talks like a duck, it must be a duck'-this is the principle we follow. This is called duck typing. From the previous example, we can understand that the behavior of the talk() method is changing depending on the object type.This is an example for polymorphism of methods.

We can rewrite Program where we can check whether the object passed to the call_talk() method has the method that is being invoked or not. This is done by rewriting the method as:

CopiedCopy Code

def call_talk(obj): 
   if hasattr(obj, 'talk'):      #if obj has talk() method then 
      obj.talk()                      #call it on the object 
   elif hasattr(obj, 'bark'): #if obj has bark() method then 
      obj.bark() #call it

In the preceding code, we are checking whether the object has a method or not with the help of hasattr() function. This function is written in the form of:

hasattr(object, attribute)

Here,'attribute' may be a method or variable.

If it is found in the object (i.e. in the class to which the object belongs) then this method returns True, else False.

Checking the object type (or class) in this manner is called 'strong typing'.

Python Object Method exists Example
CopiedCopy Code

class Dog: 
   def bark(self): 
      print('Bow, bow!') 
class Duck: 
   def talk(self): 
      print('Quack, quack!') 
class Human: 
   def talk(self): 
      print('Hello, hi!') 
def call_talk(obj): 
   if hasattr(obj, 'talk'): 
      obj.talk() 
   elif hasattr(obj, 'bark'): 
      obj.bark() 
   else: 
      print('Wrong object passed...') 
x = Duck() 
call_talk(x) 
x = Human() 
call_talk(x) 
x = Dog() 
call_talk(x)