Details the duck types of Python

  • 2020-05-10 18:28:50
  • OfStack

Duck type basic definition

First of all, Python does not support polymorphism, nor does it support polymorphism. python is a polymorphic language that worships duck types.

Here's what wikipedia says about duck types:

In programming, duck type (English: duck typing) is a style of dynamic type. In this style, the valid semantics of an object are determined not by inheriting from a particular class or implementing a particular interface, but by the current collection of methods and properties. The concept takes its name from the duck test proposed by James Whitcomb Riley. The "duck test" can be described as follows:

"When you see a bird that walks like a duck, swims like a duck, and quacks like a duck, that bird is called a duck."

In the case of a duck type, it is not the type of the object itself that matters, but how it is used. For example, in a language that does not use duck types, we could write a function that takes an object of type duck and calls its walk and call methods. In a duck-like language, such a function can take an object of any type and call its walk and call methods. If the methods that need to be called do not exist, a runtime error will be thrown. The behavior that any object with such a correct walk and call method can be accepted by the function leads to the above statement, hence the name of this way of determining the type.

Duck types often benefit from not testing the types of parameters in methods and functions, but rather rely on documentation, clean code, and tests to ensure proper use. Users who move from statically typed languages to dynamically typed languages often try to add some static (pre-run) type checking, which affects the benefits and scalability of duck typing and constrains the dynamic nature of the language.

Concrete implementation in python

The following code is a simple type of duck


class duck():
  def walk(self):
    print('I walk like a duck')
  def swim(self):
    print('i swim like a duck')

class person():
  def walk(self):
    print('this one walk like a duck') 
  def swim(self):
    print('this man swim like a duck')

For a duck type, we don't care about the type of the object itself or the class inheritance, but how the class is used. We can call the methods of these classes with the following code.


def watch_duck(animal):
  animal.walk()
  animal.swim()

small_duck = duck()
watch_duck(small_duck)

output >> 
I walk like a duck
i swim like a duck


duck_like_man = person()
watch_duck(duck_like_man)

output >> 
this one walk like a duck
this man swim like a duck


class Lame_Foot_Duck():
  def swim(self):
    print('i am lame but i can swim')

lame_duck = Lame_Foot_Duck()
watch_duck(lame_duck)

output >>
AttributeError: Lame_Foot_Duck instance has no attribute 'walk'

watch_duck The function receives the object of the class, and instead of checking the type of the object, calls the object's walk and walk methods, and if the required method does not exist, it reports an error.

The specific representation of the duck type in python is shown in the following code


class CollectionClass():
  lists = [1,2,3,4]
  def __getitem__(self, index):
    return self.lists[index]

iter_able_object = CollectionClass()

class Another_iterAbleClass():
  lists=[1,2,3,4]
  list_position = -1

  def __iter__(self):
    return self

  def next(self): # Is there a simpler implementation that USES generators or iterators or something :)
    self.list_position += 1
    if self.list_position >3:
      raise StopIteration
    return self.lists[self.list_position]

another_iterable_object=Another_iterAbleClass()

print(iter_able_object[1])
print(iter_able_object[1:3])
output>>
2
[2, 3]

another_iterable_object[2]
output>>
Traceback (most recent call last):
 File "/Users/steinliber/a.py", line 32, in <module>
  another_iterable_object[2]
TypeError: 'Another_iterAbleClass' object does not support indexing

print(next(another_iterable_object))
output>>
1
print(next(another_iterable_object))
output>>
2

print(next(iter_able_object))
output>>
Traceback (most recent call last):
 File "/Users/steinliber/a.py", line 29, in <module>
  print(next(iter_able_object))
TypeError: IterAbleClass object is not an iterator

In python, the implementation methods of the above code are called protocol (protocol), and these protocol can be viewed as notifying interfaces that specify which methods of the object the caller needs to invoke using the functionality, and which methods the caller needs to implement to accomplish the functionality. It differs from the interface in java in that the implementation of interface functions in java requires inheritance, and the inherited class must implement all abstract methods in the interface, so the concept of type is emphasized in Java, while in python protocol More notificationally, a function specifies which methods of an incoming object need to be called to implement a function, and all the classes that implement those methods implement that function.

Specifically from the above two classes, the first class is implemented __getitem__ Method, then the python interpreter will treat it as an collection, and you can slice the objects of this class, get the subitems, and so on. The second class is implemented __iter__ and next Method, python will think of it as an iterator, and you can loop through the objects of this class to get the items. A class can implement methods that it is capable of implementing and can only be used in situations where it makes sense.

These two classes, compared to the duck class above, are actually used for edge cutting [](which actually calls python slice ) and for loops iter() Is equivalent to watch_duck Function. These functions receive objects of any class and call methods in the object needed to implement the function. If the method object called in the function does not exist in the object, an error is reported.

As you can see above, the flexibility of the python duck type is that it focuses on how the called object is used, not on what the object type itself is. So it's used in python isinstance To judge the type of the incoming parameter is not recommended, however pythonic The method is to directly use the parameters passed in through try, protocol0 To handle incoming parameters that do not meet the requirements. We should use the object by its capabilities, not its type.

conclusion

The above is the detailed introduction of Python duck types. The content of this paper is still very detailed. I hope it will be helpful for you to learn python.


Related articles: