Python的鸭子类型和多态

Python的鸭子类型和多态

一、鸭子类型

当你看见一只鸟走起来像鸭子,游起泳来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子

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

class Dog(object):
    def say(self):
        print("i am a dog")
        
class Duck(object):
    def say(self):
        print("i am a duck")
        
animal = Cat()
animal.say() # i am a cat

上面三个类中都包含了say方法。

先实例化一个animal对象,然后在运行时可能给它赋值成CatDog或者Duck,所以是不确定的。

java中实现多态,一般是这样做,先定义一个父类Animal,其中包含一个say方法,然后再定义继承Animal类的Cat子类,并在Cat子类中重写say方法,这样才能指明CatAnimal的子类。

基于java思想,用python语言来实现多态概念

class Animal:
	def say(self):
        print("i am a animal")
class Cat(Animal):
	def say(self):
        print("i am a cat")      

Animal an = Cat() 
#在java中声明变量时需要定义变量类型,python中不能这样写
 an.say() #调用子类方法

而在Python中实例化的对象是一个动态的变量,可以指向任何类型,指需要在类中把方法写出来即可。如下边得代码一样。

animal_list = [Cat,Dog,Duck]
for animal in animal_list:
	animal().say()
# i am a cat
# i am a dog
# i am a duck

当各类实现了共同的方法名,就可以循环调用同一个方法,实现了多态,相比java中需要继承一个父类再重写类的方法而言就简单多了。

也就是说当所有类或对象实现了共同的方法,这个方法名也一样,那这些类就可以归为一种类型。

二、下面再来看一个例子

a = ["bobby1", "bobby2"]

b = ["bobby2", "bobby"]
name_tuple = ["bobby3", "bobby4"]
name_set = set()
name_set.add("bobby5")
name_set.add("bobby6")
a.extend(b)
print(a) # ["bobby1", "bobby2","bobby2", "bobby"]

想一个问题,extend函数只能穿进来一个列表吗?

在源码中extend函数是这样定义的

 def extend(self, iterable: Iterable[_T]) -> None: ...

所以说extend函数不光可以用list作为参数,任何可以迭代的对象都是可以的,而在Pythontupleset都是可迭代的对象。

所以往extend函数中传name_setname_tuple都可以。

a = ["bobby1", "bobby2"]

name_tuple = ["bobby3", "bobby4"]
name_set = set()
name_set.add("bobby5")
name_set.add("bobby6")
# a.extend(name_tuple)
# print(a) # ["bobby1", "bobby2","bobby3", "bobby4"]
a.extend(name_set)
print(a) # ["bobby1", "bobby2","bobby5", "bobby6"]

三、往extend函数中传入可迭代的类

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    def __getitem__(self, item):
        return self.employee[item]

    def __len__(self):
        return len(self.employee)

company = Company(["tom", "bob", "jane"])

a = ["bobby1", "bobby2"]

a.extend(company)
print(a) # ["bobby1", "bobby2","tom", "bob", "jane"]

extend函数会隐含调用对象中的迭代器,比如__iter____getitem__之类的(调用之后就变成可迭代的对象了)。

小节

在python中魔法函数充分利用了鸭子类型,在对象中写入很多魔法函数,可以被python解释器本身识别,在很多python内置的对象或内置的类中都具有非常好用的特性,比如可迭代的特性,上下文管理器、集合序列相关特性等,代码本身更加灵活。

猜你喜欢

转载自blog.csdn.net/weixin_43901214/article/details/106922084
今日推荐