python小白学习笔记《11.类与对象2》

python小白学习笔记《11.类与对象2》

类能成为面向对象编程的主要工具,帮助 Python 在编程世界打下一片疆土,很大程度上是基于它的继承和定制。

0.类的继承和定制是什么?

0.0继承,从广东人说起

假设你有个外国朋友,刚来中国。某天,他看到“广东人”这个词,就来问你,你会怎么跟他解释?

可能你会回答:广东是中国的一个地方。广东人就是中国人。他可能会复述:哦!原来就是中国人。

深究的话,“广东人就是中国人”中的“就是”的确切含义是“属于”,即广东人属于中国人。

因此,中国人有的属性(如黑头发)和方法(如用筷子),广东人也都有。这么一来,用一句话“广东人是中国人”,便能让他接受多个信息:广东人有黑头发,会用筷子……

这个过程相当于:把他脑子里对“中国人”这个类的所有信息都复制了一份,然后放到了“广东人”这个类下面。

我们通过事物的归属关系,使信息的传递更为高效。听到“Python是一种计算机语言”,我们就知道Python可以编程;看到“云浮市在广东省”,我们就明白云浮市在中国南方……

同样的,编程世界也是如此。我们也可以用一句话,让计算机知道:A类属于B类,自然也拥有了B类的所有属性和方法。这句话在编程里就是:A类继承了B类。

在Python中,我们的习惯表述是:A类是B类的子类,而B类是A类的父类(或超类)。

所以,类的继承,让子类拥有了父类拥有的所有属性和方法。如此,不用白手起家(从头写代码),直接一夜暴富(代码的复用)。

不过,只有继承的话,子类只是父类的复制而已。那样,为什么不直接用父类,还要增加一个子类?

要回答这个问题,就需要了解另一个重要的概念:类的定制。

0.1定制,广东人又来了

还是说回广东人,广东人除了继承中国人的属性方法外,还可以创造【属于自己】的属性或方法,如籍贯开头是广东省(属性)、会说广东话(方法)。
上面的操作,都可以说是广东人在继承的基础上又做了定制。

同样,子类也可以在继承的基础上进行个性化的定制,包括:(1)创建新属性、新方法;(2)修改继承到的属性或方法。

简而言之:类的定制,不仅可以让子类拥有新的功能,还能让它有权修改继承到的代码——在写这句话时,我仿佛看到子类化成了一个人,抬头瞟了一眼在他上方的父类,淡淡地说了一句话:以我为主,为我所用。

1.类的继承,要怎么写?

1.0继承的基础语法

用代码表示继承,语句是:

class A(B):
#A为子类名,B为父类名

子类继承的属性和方法,也会传递给子类创建的实例。

class Chinese:
    eye = 'black'

    def eat(self):
        print('吃饭用筷子。')

class Cantonese(Chinese):
    pass # pass表示'跳过',不执行其他操作

Maria = Cantonese()
print(Maria.eye)
Maria.eat()

在这里插入图片描述
实例Maria 是Cantonese(广东人)这个类创建的实例,却拥有Chinese才有的属性和方法。原因是Maria继承了Cantonese.

可见:通过一个小括号,子类就能轻轻松松地拥有父类所拥有的一切。不用复制大段大段的代码,只要一个括号,就能复用整块代码。

很多类在创建时也不带括号,如class Chinese:。这意味着它们没有父类吗?

并不。实际上,class Chinese:在运行时相当于class Chinese(object):。而object,是所有类的父类,我们将其称为根类(可理解为类的始祖)。

我们可以用一个函数来验证这一点:函数isinstance(),可以用来判断某个实例是否属于某个类。

具体用法是输入两个参数(第一个是实例,第二个是类或类组成的元组),输出是布尔值(True 或 False)。

print(isinstance(1,int))
# 判断1是否为整数类的实例
print(isinstance(1,str))

print(isinstance(1,(int,str)))
# 判断实例是否属于元组里几个类中的一个

在这里插入图片描述
正式验证:

class Chinese:
    pass

class Cantonese(Chinese):
    pass

gonger = Chinese()
# 宫二,电影《一代宗师》女主,生于东北
yewen = Cantonese()
# 叶问,电影《一代宗师》男主,生于广东

print('\n验证1:子类创建的实例同时也属于父类')
print(isinstance(gonger,Chinese))  
print(isinstance(yewen,Chinese))  

print('\n验证2:父类创建的实例不属于子类。')
print(isinstance(gonger,Cantonese))

print('\n验证3:类创建的实例都属于根类。')
print(isinstance(gonger,object))  
print(isinstance(yewen,object))

在这里插入图片描述
所以,在类的继承中,不仅子类属于父类,子类所创建的实例实际上也同时属于父类。

理论上,父类可以被无限个子类所继承(这一点好比类的属性方法可以传递给无限个实例)。

1.1类的继承之多层继承

继承不仅可以发生在两个层级之间(即父类-子类),还可以有父类的父类、父类的父类的父类……

class Earthman:
    eye_number = 2

# 中国人继承了地球人
class Chinese(Earthman):
    eye_color = 'black'

# 广东人继承了中国人,同时也继承了地球人。
class Cantonese(Chinese):
    pass

yewen = Cantonese()
print(yewen.eye_number)
print(yewen.eye_color)

在代码最后两行,我们看到:实例yewen可以调用父类Chinese和父类的父类Earthman中的属性。可得结论:子类创建的实例可调用所有层级父类的属性和方法。

1.2类的继承之多重继承

一个类,可以同时继承多个类,语法为class A(B,C,D):。假设我们将“出生在江苏,定居在广东的人”设为一个类Yuesu,那么,它的创建语句则为class Yuesu(Yue,Su)。

class Yuesu(Yue,Su)括号里Yue和Su的顺序是有讲究的。和子类更相关的父类会放在更左侧。我认为“出生在江苏,定居在广东的人”在穿着和饮食等方面会更接近广东人,所以将 Yue 放在 Su 的左侧。

所以,广东人创建的实例在调用属性和方法时,会先在左侧的父类中找,找不到才会去右侧的父类找。(可理解为“就近原则”)

class Su:
    born_city = 'Jiangsu'
    wearing = 'thick'  # 穿得较厚

    def diet(self):
        print('我们爱吃甜。')

class Yue:
    settle_city = 'Guangdong'
    wearing = 'thin'  # 穿得较薄

    def diet(self):
        print('我们吃得清淡。')

class Yuesu(Yue,Su):
    pass

xiaoming = Yuesu()
print(xiaoming.wearing)
print(xiaoming.born_city)
xiaoming.diet()

在这里插入图片描述

2.类的定制,要怎么写?

2.0定制,可以新增代码

class Chinese:
    eye = 'black'

    def eat(self):
        print('吃饭,选择用筷子。')

class Cantonese(Chinese):  # 类的继承
    native_place = 'guangdong'  # 类的定制

    def dialect(self):  # 类的定制
        print('我们会讲广东话。')

yewen = Cantonese()
print(yewen.eye)
# 父类的属性能用
print(yewen.native_place)
# 子类的定制属性也能用
yewen.eat()
# 父类的方法能用
yewen.dialect()
# 子类的定制方法也能用

可见:我们可以在子类下新建属性或方法,让子类可以用上父类所没有的属性或方法。这种操作,属于定制中的一种:新增代码。
在这里插入图片描述
除了新增代码外,定制还有另一种操作:重写代码。

2.1定制,也可重写代码

重写代码,是在子类中,对父类代码的修改。

class Chinese:

    def land_area(self,area):
        print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)

class Cantonese(Chinese):
    # 间接对方法进行重写
    def land_area(self, area, rate = 0.0188):
        Chinese.land_area(self, area * rate)
        # 直接继承父类方法,再调整参数。

gonger = Chinese()
yewen = Cantonese()
gonger.land_area(960)
yewen.land_area(960)

子类继承父类方法的操作是在def语句后接父类.方法(参数),如上述代码的第八、九行。

这样一来,父类方法land_area中的说法改变,子类也不用去动,因为子类直接继承了父类的方法。只不过,在继承的基础上,通过参数的调整完成了定制。

这便是定制:在复用代码的基础上,又能满足个性化的需求。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值