python的类方法可以用对象和类名来调用吗_python类与对象:继承,调用未绑定的父类方法实例讲解...

目录:

一、继承

二、调用未绑定的父类方法

三、使用super函数

四、多重继承

五、课时38课后习题及答案

现在需要扩展游戏,对鱼类进行细分,有金鱼(Goldfish)、三文鱼(Salmon)、鲤鱼(Carp),还有鲨鱼(Shark)。那么我们来思考一个问题:能不能不要每次都从头到尾去重新定义一个新的鱼类呢?因为我们知道大多数鱼的属性和方法是相似的,如果有一种机制可以让这些相似的东西得以自动传递,那就方便快捷多了。这种机制就是今天要讲的:继承。

***********

一、继承

***********

语法很简单:

class类名(被继承的类):

...

被继承的类称为基类、父类或超类;继承者称为子类,一个子类可以继承它的父类的任何属性和方法。举个例子:

>>> classParent:defhello(self):print("正在调用父类的方法...")>>> classChild(Parent):pass

>>> p =Parent()>>>p.hello()

正在调用父类的方法...>>> c =Child()>>>c.hello()

正在调用父类的方法...

需要注意的是:如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性:

>>> classChild(Parent):defhello(self):print("正在调用子类的方法...")>>> c =Child()>>>c.hello()

正在调用子类的方法...

好,那尝试一下刚才提到的金鱼(Goldfish)、三文鱼(Salmon)、鲤鱼(Carp),还有鲨鱼(Shark)的例子:

#p11-2.py

importrandom as rclassFish:def __init__(self):

self.x= r.randint(0, 10)

self.y= r.randint(0, 10)defmove(self):#这里主要演示类的继承机制,就不考虑检查场景边界和移动方向的问题

#假设所有鱼都是一路向西游

self.x -= 1

print("我的位置是:", self.x, self.y)classGoldfish(Fish):pass

classCarp(Fish):pass

classSalmon(Fish):pass

#上边几个都是食物,食物不需要有个性,所以直接继承Fish类的全部属性和方法即可#下边定义鲨鱼类,这个是吃货,除了继承Fish类的属性和方法,还要添加一个吃的方法

classShark(Fish):def __init__(self):self.hungry=Truedefeat(self):ifself.hungry:print("吃货的梦想就是天天有的吃^_^")

self.hungry=Falseelse:print("太撑了,吃不下了!")

>>> #先运行p11-2.py

>>> fish =Fish()>>> #试试小鱼儿能不能动

>>>fish.move()

我的位置是:70>>> goldfish =Goldfish()>>>goldfish.move()

我的位置是:2 2

>>>goldfish.move()

我的位置是:1 2

>>>goldfish.move()

我的位置是: 02

>>> #可见金鱼确实在一路向西

>>> #下面尝试生成鲨鱼

>>> shark =Shark()>>> #试试这货能不能吃东西?

>>>shark.eat()

吃货的梦想就是天天有的吃^_^

>>>shark.eat()

太撑了,吃不下了!>>>shark.move()

Traceback (most recent call last):

File"", line 1, in shark.move()

File"C:Users14158Desktoplalallalalal.py", line 13, inmove

self.x-= 1AttributeError:'Shark' object has no attribute 'x'

奇怪!同样是继承于Fish类,为什么金鱼(goldfish)可以移动,而鲨鱼(shark)一移动就报错呢?

其实这里抛出的异常说得很清楚了:Shark对象没有x属性。原因其实是这样的:在Shark类中,重写了魔法方法_ _init_ _,但新的_ _int_ _方法里边没有初始化鲨鱼的x坐标和y坐标,因此调用move方法就会出错。那么解决这个问题的方案就很明显了,应该在鲨鱼类中重写_ _int_ _方法的时候先调用基类Fish的_ _init_ _方法。

下面介绍两种可以实现的技术:

(1)调用未绑定的父类方法

(2)使用super函数

*******************************

二、调用未绑定的父类方法

*******************************

看以下代码:

classShark(Fish):def __init__(self):

Fish.__init__(self)

self.hungry= True

再运行下,发现鲨鱼可以移动了:

>>> #先运行修改后的p11-2.py

>>> shark =Shark()>>>shark.move()

我的位置是:60>>>shark.move()

我的位置是:50>>>shark.move()

我的位置是:4 0

这里需要注意的是这个self并不是父类Fish的实例对象,而是子类Shark的实例对象,所以这里说的未绑定是指并不需要绑定父类的实例对象,使用子类的实例对象代替即可。

在Python中有一个更好的方案可以代替它,就是使用super函数。

**********************

三、使用super函数

**********************

super函数能够帮我们自动找到基类的方法,而且还为我们传入了self参数,这样就不需要做这些事了:

classShark(Fish):def __init__(self):

super().__init__()

self.hungry= True

运行后会得到同样的结果。

super函数的“超级”之处在于你不需要明确给出任何基类的名字,它会自动帮你找到所有基类以及对应的方法。由于你不用给出基类的名字,这就意味着如果需要改变类继承关系,只要改变class语句里的父类即可,而不必要在大量代码中去修改所有被继承的方法。

****************

四、多重继承

****************

除此之外Python还支持多继承,就是可以同时继承多个父类的属性和方法:

class类名(父类1,父类2,父类3,...):

...

>>> classBase1:deffoo1(self):print("我是foo1,我在Base1中...")>>> classBase2:deffoo2(self):print("我是foo2,我在Base2中...")>>> classC(Base1,Base2):pass

>>> c =C()>>>c.foo1()

我是foo1,我在Base1中...>>>c.foo2()

我是foo2,我在Base2中...

上面就是基本的多重继承的语法。但多重继承其实很容易导致代码混乱,所以当你不确定是否真的必须使用多重继承的时候,请尽量避免使用它,因为有些时候会出现不可预见的BUG。

*******************************

五、课时38课后习题及答案

*******************************

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值