Python类和对象--多态(三)

多态

第一次接触多态,之前没有学习过java中关于多态到底是怎么说明的,听说java的多态和Python的很不一样,这里我只是说一下针对于Python方面我对多态的理解;

什么是多态呢?

顾名思义多态就是多种状态,多态使用的前提是继承以及方法重写

我们知道Python中的变量定义是不需要指定类型的,只有在给它第一次赋值的时候它的类型才会随之确定,但也并不是之后就会保持一成不变,它随着引用对象的改变而改变,比如:

#定义变量 a = True,它的意思并不是 a 就是 True,a 只是 True 的一个引用
#我们可以定义许多变量,它们都可以是True的引用,当然在引用之后,它们的类型都是bool型
a = True 
print(type(a)) #<class 'bool'>

#那么 a 从此之后就是 bool 型的了吗?当然不能这么说,我们可以让 a 成为其它数据的引用
a = [1,2,3,4]
print(type(a)) #<class 'list'> 
# a又成为了list类型

这个例子与Python中的多态联系不大,只是作为一个引子;
接下来进入正题:

在学类和对象时我们学到了继承,接下来随便写一个例子:

class Animal():
    def __init__(self,name):
        self.name = name
    def running(self):
        print(self.name.title() + " is running.")
class Cat(Animal):
    pass
class Dog(Animal):
    pass

如上有三个类,其中Cat和Dog都继承自Animal,那么想一想,Cat和Dog的数据类型可以是Animal吗?

c = Cat('Tom')
print(isinstance(c,Cat)) # True
print(isinstance(c,Animal)) #True

可以看到,子类Cat既是Cat类型,又是Animal类型,这就有点意思了,但真正有意思的还不止于此:

class Animal():
    def __init__(self,name):
        self.name = name
    def running(self):
        print(self.name.title() + " is running.")
class Cat(Animal):
    pass
class Dog(Animal):
    pass
class Bird(Animal):
    def flying(self):
        print(self.name.title() + " is flying.")
def text(obj):
    obj.running()

在这段代码中,我定义了一个父类、三个子类和一个函数,这个函数传入一个参数,运行它的running方法;

c = Cat('Tom')
d = Dog('Acai')
b = Bird('Pink')

text(c)
text(d)
text(b)

##
Tom is running.
Acai is running.
Pink is running.

可以看到,Cat对象、Dog对象、Bird对象都成功执行了text函数,虽然Bird对象并没有执行我们期望的flying方法,但那是因为我们的函数写的是执行running方法的缘故;

可是为什么这些对象都能成功执行text()函数,并调用出了Animal对象中的running方法呢?
你可能会认为因为它们都继承自Animal,它们也都属于Animal类型,但事实上,我们不妨再看一个例子:

class Animal():
    def __init__(self,name):
        self.name = name
    def running(self):
        print(self.name.title() + " is running.")
class Dog(Animal):
    pass
class Smalldog(Dog):
    pass
class Cat():
    def __init__(self,name):
        self.name = name
    def running(self):
        print(self.name.title() + " is running.")
def text(obj):
    obj.running()
        
sd = Smalldog('jack')
c = Cat('biubiu')
text(sd)
text(c)

##
Jack is running.
Biubiu is running.

在这个例子中,第一个证明了子类的子类依然能够成功执行text函数,使用running方法,但第二个呢?这次的Cat对象不是任何类的子类。

这时你就会发现所有这些都有一个通性,即它们都有running方法,事实上text传入的参数是obj,它本来就是不明确类型的,而text函数又用到了obj的running方法,那么Python就会依次作为判断依据,只要传入的对象含有running方法,那么它就是合法的,如果没有那就报错;

这就是Python作为动态语言的一个显著特点----鸭子类型;即一个对象“只要看起来像鸭子,走起路来也像”,那么它就可以看作鸭子;

对于上文的text函数来说,它要传入的就是一只鸭子,而只要含有running方法的任何对象,Python都会把它当作鸭子看待,而不要求传入的必须是父类或者子类这种严格规定;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值