时间:2021-05-22
鸭子类型基本定义
首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。
以下是维基百科中对鸭子类型得论述:
在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。
鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。
python中的具体实现
下面的代码就是一个简单的鸭子类型
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')对于一个鸭子类型来说,我们并不关心这个对象的类型本身或是这个类继承,而是这个类是如何被使用的。我们可以通过下面的代码来调用这些类的方法。
def watch_duck(animal): animal.walk() animal.swim()small_duck = duck()watch_duck(small_duck)output >> I walk like a ducki swim like a duckduck_like_man = person()watch_duck(duck_like_man)output >> this one walk like a duckthis man swim like a duckclass 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函数接收这个类的对象,然后并没有检查对象的类型,而是直接调用这个对象的走和游的方法,如果所需要的方法不存在就报错。
具体在python中鸭子类型的体现如下面的代码所示
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: 'Another_iterAbleClass' object does not support indexingprint(next(another_iterable_object))output>>1print(next(another_iterable_object))output>>2print(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在python把上述代码的实现方法叫做protocol(协议),这些protocol可以看作是通知型的接口,它规定了调用方使用该功能要调用对象的哪些方法,被调用方要实现哪些方法才能完成这个功能。它和java中的接口区别在于java中的接口功能实现需要通过继承,继承的类必须实现接口中的所有的抽象方法,所以在Java中强调的是类型的概念,而python中的protocol更多的是通知性的,一个函数规定要实现某个功能需要调用传入对象的哪些方法,所有实现这些方法的类就可以实现这个功能。
具体从上面两个类来说,第一个类实现了__getitem__方法,那python的解释器就会把它当做一个collection,就可以在这个类的对象上使用切片,获取子项等方法,第二个类实现了__iter__和next方法,python就会认为它是一个iterator,就可以在这个类的对象上通过循环来获取各个子项。一个类可以实现它有能力实现的方法,并只能被用于在它有意义的情况下。
这两个类和上面的鸭子类相比较,其实用于切边的[](它其实调用的是python的slice函数)和用于循环的iter()就相当于watch_duck函数,这些函数都接收任意类的对象,并调用实现功能所需要的对象中的方法来实现功能,若该函数中调用的方法对象里面不存在,就报错。
从上面可以看出,python鸭子类型的灵活性在于它关注的是这个所调用的对象是如何被使用的,而没有关注对象类型的本身是什么。所以在python中使用isinstance来判断传入参数的类型是不提倡的,更pythonic的方法是直接使用传入的参数,通过try,except来处理传入参数不符合要求的情况。我们应该通过传入对象的能力而不是传入对象的类型来使用该对象。
总结
以上就是Python鸭子类型的详细介绍,本文内容介绍的还是很详细的,希望对大家学习python能有一定的帮助,如果有疑问大家可以留言交流。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
首先Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。在程序设计中,鸭子类型(英语:ducktyping)是动态类型的一种风格。
在程序设计中,鸭子类型(英语:ducktyping)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法
这篇文章给大家介绍Python中的defaultdict数据类型,具体内容如下所示:官方网址首先,defaultdict是dict的一个子类。通常Python中
今天来说说编程语言中的动态类型语言与鸭子类型。动态语言维基百科对动态语言的定义:动态编程语言是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以
前言本文主要给大家介绍了关于python子类调用父类函数的相关内容,Python中子类中的__init__()函数会覆盖父类的函数,一些情况往往需要在子类里调用