Home  >  Article  >  Backend Development  >  A detailed introduction to Python’s duck typing

A detailed introduction to Python’s duck typing

高洛峰
高洛峰Original
2017-02-23 11:18:411555browse

I believe that Python developers are familiar with Python’s duck typing. The accurate definition of duck typing in Wikipedia is ‘a style of dynamic typing. In this style, the effective semantics of an object are not determined by inheriting from a specific class or implementing a specific interface, but by the "current set of methods and properties". So this article gives you the duck typing of python.

Basic definition of duck type

First of all, Python does not support polymorphism, and it does not need to support polymorphism. Python is a kind of polymorphism. Language, advocating duck typing.

The following is a discussion of duck typing from Wikipedia:

In programming, duck typing (English: duck typing) is a style of dynamic typing. In this style, the effective semantics of an object are determined not by inheriting from a specific class or implementing a specific interface, but by the current set of methods and properties. The name of this concept comes from the duck test proposed by James Whitcomb Riley. The "duck test" can be expressed like this:

"When you see a bird that walks like a duck, swims like a duck, and quacks like a duck, If it looks like a duck, the bird can be called a duck."

In duck typing, the focus is not on the type of the object itself, but on how it is used. For example, in a language that doesn't use duck typing, we could write a function that takes an object of type duck and calls its walk and bark methods. In a language that uses duck typing, such a function can accept 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 raised. The fact that any object with the correct walk and call methods can be accepted by a function leads to the above statement, hence the name of this way of determining types.

Duck typing often benefits from not testing the types of parameters in methods and functions, but instead relying on documentation, clear code, and testing to ensure correct usage. Users moving from statically typed languages ​​to dynamically typed languages ​​often attempt to add some static (before runtime) type checking, thereby compromising the benefits and scalability of duck typing and constraining the dynamic nature of the language.

Specific implementation in python

The following code is a simple duck type

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 inheritance of the class, but how the class is used. We can call the methods of these classes through 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_duckThe function receives the object of this class, and then does not check the type of the object, but directly calls the sum of the object If the required method does not exist, an error will be reported.

The specific embodiment of duck type in python is as 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): #还有更简单的实现,使用生成器或迭代器什么的:)
    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: &#39;Another_iterAbleClass&#39; 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 method of the above code is called protocol ( Protocol), these protocols can be regarded as notification interfaces, which specify which methods of the object the caller needs to call to use this function, and which methods the callee needs to implement to complete this function. The difference between it and the interface in Java is that the interface function in Java needs to be implemented through inheritance. The inherited class must implement all the abstract methods in the interface, so the concept of type is emphasized in Java, while protocol in python It is more informative. A function specifies which methods of the incoming object need to be called to implement a certain function. All classes that implement these methods can implement this function.

Specifically speaking from the above two classes, the first class implements the __getitem__ method, then the python interpreter will treat it as a collection, and the objects of this class can be Use slicing, get sub-items and other methods. If the second class implements the __iter__ and next methods, python will think it is an iterator, and you can use it on the object of this class. Loop through each child item. A class can implement methods that it is capable of implementing, and can only be used in situations where it makes sense.

Compared with the duck class above, these two classes are actually [] used for edge cutting (it actually calls python's slice function) and ## used for looping. #iter() is equivalent to the watch_duck function. These functions receive objects of any class and call methods in the objects required to implement the function to implement the function. If the method called in the function If the object does not exist, an error will be reported.

As can be seen from the above, the flexibility of python duck typing is that it focuses on how the called object is used, rather than what the object type itself is. Therefore, it is not recommended to use

isinstance in python to determine the type of incoming parameters. A more pythonic method is to directly use the incoming parameters through try, exceptTo handle the situation where the incoming parameters do not meet the requirements. We should use the object by passing in its capabilities rather than passing in the object's type.

Summary

The above is a detailed introduction to Python duck types. The content of this article is still very detailed. I hope it will be helpful to everyone learning python. , if you have any questions, you can leave a message to communicate.

For more detailed articles on Python’s duck type, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn