AdvancePython-python中的鸭子类型

多态:说到多态,我们会想到java、c#这样的强类型语言,多态最核心的思想就是,父类的引用可以指向子类的对象,或者接口类型的引用可以指向实现该接口的类的实例。多态之所以是这样的是因为基于一个事实:子类就是父类!调用不同的子类将会产生不同的行为,而无须明确知道这个子类实际上是什么,这是多态的重要应用场景。

1.在Java或C#中定义函数参数或声明变量时,必须指定参数或变量的类型, 如果限定了某一种类型,那么另外一种类型是不被采纳的。所以在这些语言的多态中,我们必须继承一个父类,并且重写父类的方法,在实例化时指定父类类型,然后将子类的实例化赋值给它。我们举个例子:

class Animal():
    def say(self):
        pass

class Dog(Animal):
    def say(self):         #对父类say方法进行重写
        print('i am a dog')

Animal animal = Dog()  #父类引用指向子类对象
animal.say()           #调用say方法,会打印出i am a dog

2.而在python中,函数参数可以是任何类型,它不关心你属于什么类,都可以进行传递。

class Cat(object):
    def say(self):
        print('i am a cat')

class Duck(object):
    def say(self):
        print('i am a duck')

class Dog(object):
    def say(self):
        print('i am a dog')

animal = Cat()
animal.say()

animal_list = [Cat,Duck,Dog]
for animal in animal_list:
    animal().say()

结果: 

 可以看出,以上三个类拥有同样的方法say,假设我们想调用Cat类,并利用它的方法say(),我们传入Dog、Duck类也一样能运行,python并不会检查对象的类型是不是Cat,只要他拥有say()方法,就可以正确的被调用。 

所以在python的多态中,无需继承,只要类拥有相同的方法,即可实现.

鸭子类型:"当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。"

在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象(前提是这些对象也有“走”和“叫”方法),并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。

python中的鸭子类型允许我们使用任何提供所需方法的对象,而不需要迫使它成为一个子类。

再举一个例子:

a = ['hobby1','hobby2']
b = ['hobby3','hobby4']
name_tuple = ('tuple1','tuple2')
name_set = set()
name_set.add('set1')
name_set.add('set2')
a.extend(name_set) #其参数为iterable任何可迭代的对象(b,name_tuple,name_set)
print(a)

结果: 

该例中,extend的原型为:extend(self,iterable),iterable为可迭代的对象,实际上在python中,set,tuple,list都是可迭代的对象,所以对于这些内建类型,甚至是我们自己定义的类型(前提是要实现__getitem__方法,成为可迭代类型),python不管他们到底是什么类型,只要是可迭代对象,都可以传入extend做其参数。里面会自动调用迭代器,然后进行for循环,把它加入到list中。

发布了16 篇原创文章 · 获赞 4 · 访问量 1783

猜你喜欢

转载自blog.csdn.net/qq_40509206/article/details/103469460
今日推荐