15 类的继承——创建子类

9.3 类的继承

编写类时可以使用已经编写好的类(类似于调用)时就要用到继承。
一个类继承另一个类:原有的类称为【父类】,新的类叫做【子类】。
子类将获得父类的所有【属性和方法】,并且子类还可以定义自己的属性和方法;在子类中也可以修改父类中的【方法】。

1 创建子类的方法

下面还是以上篇中汽车的类为父类,创建它的子类。
#*******************这一段是之前创建的汽车类**********************#
class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #这儿有必要先赋一个值,因为下面默认无实参传递给它
    
    def get_descriptive_name(self):
        """返回整洁的汽车描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()  
    
    def read_odometer(self):
        """打印一条汽车里程的信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
    def update_odometer(self, mileage):
        """
        将里程表读数设置为指定的值
        并禁止将里程表的读数往回调
        """
        if mileage >= self.odometer_reading:  #里程数必须 ≥ 当前的里程读数
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
            
    def increment_odometer(self, miles):
        """里程表读数增加指定的量"""
        self.odometer_reading += miles
#*******************这一段是之前创建的汽车类**********************#

###上面的叫父类,下面我们开始创建它的子类 --- 电动汽车类(它属于汽车但是又有自己的特点)
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)       
#下面我们开始使用这个[子类]试一试
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
#注意这里的get_descriptive_name()函数是从新创建的子类里调用的!

Result

2016 Tesla Model S

【注意点】:
①创建子类时父类必须包含在当前界面
②必须在子类的括号中指明父类的名称class ElectricCar(Car):
③第一个方法__init__接受创建Car类所需的信息(注意这儿有self
super()函数是让子类和父类连接起来,就是调用父类的【方法】__init__(注意这儿没有self
⑤创建实例的时候调用子类 --- 子类自动向父类寻找

2 当然你还可以给子类新增属于他自己的【方法和属性】

#*******************这一段是之前创建的汽车类**********************#
class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #这儿有必要先赋一个值,因为下面默认无实参传递给它
    
    def get_descriptive_name(self):
        """返回整洁的汽车描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()  
    
    def read_odometer(self):
        """打印一条汽车里程的信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
    def update_odometer(self, mileage):
        """
        将里程表读数设置为指定的值
        并禁止将里程表的读数往回调
        """
        if mileage >= self.odometer_reading:  #里程数必须 ≥ 当前的里程读数
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
            
    def increment_odometer(self, miles):
        """里程表读数增加指定的量"""
        self.odometer_reading += miles
#*******************这一段是之前创建的汽车类**********************#

###上面的叫父类,下面我们开始创建它的子类 --- 电动汽车类(它属于汽车但是又有自己的特点)
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """
        电动汽车的独特之处
        初始化父类的属性,再初始化子类的属性
        """    
        super().__init__(make, model, year) 
        self.battery_size = 70    #新增的子类属性,需要初始化
    
    #下面我们开始创建新的方法来表述这个电瓶的相关信息
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-KWh battery.")
#下面我们利用新的方法创建实例
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name()) #用于返回整洁的信息
my_tesla.describe_battery() #调用新的方法describe_battery()

Result:

2016 Tesla Model S
This car has a 70-KWh battery.


3 还可以更改父类已有的方法

#*******************这一段是之前创建的汽车类**********************#
class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #这儿有必要先赋一个值,因为下面默认无实参传递给它
    
    def get_descriptive_name(self):
        """返回整洁的汽车描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()  
    
    def read_odometer(self):
        """打印一条汽车里程的信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
    def update_odometer(self, mileage):
        """
        将里程表读数设置为指定的值
        并禁止将里程表的读数往回调
        """
        if mileage >= self.odometer_reading:  #里程数必须 ≥ 当前的里程读数
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
            
    def increment_odometer(self, miles):
        """里程表读数增加指定的量"""
        self.odometer_reading += miles
#*******************这一段是之前创建的汽车类**********************#

###上面的叫父类,下面我们开始创建它的子类 --- 电动汽车类(它属于汽车但是又有自己的特点)
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """
        电动汽车的独特之处
        初始化父类的属性,再初始化子类的属性
        """    
        super().__init__(make, model, year) 
        self.battery_size = 70    #新增的子类属性,需要初始化
    
    #下面我们开始创建新的方法来表述这个电瓶的相关信息
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-KWh battery.")
        
    #更改父类已有的属性(重新定义即可) --- 假设父类有 fill_gas_tank这一方法
    def fill_gas_tank(self):
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")
        
#开始创建实例 --- 假设调用了方法fill_gas_tank
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name()) #用于返回整洁的信息
my_tesla.describe_battery() #调用新的方法describe_battery()
my_tesla.fill_gas_tank()    #假设我们调用了fill_gas_tank方法查看油箱信息
【子类既可以新增也可以修改】就是继承可以对父类 --- 取其精华,去其糟粕

Result:

2016 Tesla Model S
This car has a 70-KWh battery.
This car doesn't need a gas tank!


4 有时候类中的【方法】太多,总会让人不想看下去,为此可以将类的一部分提取出来作为新的类——意思就是再细分类。

例如将ElectricCar类中的关于电池的一些方法划分成一个新类 --- Battery类
#*******************这一段是之前创建的汽车类**********************#
class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #这儿有必要先赋一个值,因为下面默认无实参传递给它
    
    def get_descriptive_name(self):
        """返回整洁的汽车描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()  
    
    def read_odometer(self):
        """打印一条汽车里程的信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
    def update_odometer(self, mileage):
        """
        将里程表读数设置为指定的值
        并禁止将里程表的读数往回调
        """
        if mileage >= self.odometer_reading:  #里程数必须 ≥ 当前的里程读数
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
            
    def increment_odometer(self, miles):
        """里程表读数增加指定的量"""
        self.odometer_reading += miles
#**********************以下是单独的电池类*************************#
class Battery():
    """一次模拟电动汽车电瓶的简单尝试"""
    
    def __init__(self, battery_size=70):#初始化形参的值时最好不要加空格!
        """初始化电瓶的属性"""            #在这里我们定义了一个可选形参battery_size
        self.battery_size = battery_size
        
    def describe_battery(self):
        """打印一条描述电池容量的信息"""
        print("This car has a " + str(self.battery_size) + "-KWh batttery.")
#************************以下是子类****************************#    
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """
        电动汽车的独特之处
        初始化父类的属性,再初始化子类的属性
        """    
        super().__init__(make, model, year) 
        self.battery = Battery()   #****直接将 Battery类作为其中的一个[方法]****#
        
#开始创建实例
my_tesla = ElectricCar('tesla', 'model s', 2016)

print(my_tesla.get_descriptive_name()) #用于返回整洁的信息
my_tesla.battery.describe_battery() 
#调用battery就是调用类 Battery,Battery再调用其中的describe_battery()来描述电瓶

Result:

2016 Tesla Model S
This car has a 70-KWh batttery.


5 下面再给Battery类添加一个【方法】,使它能够根据电池容量大小报告可行驶的里程数。

#*******************这一段是之前创建的汽车类**********************#
class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #这儿有必要先赋一个值,因为下面默认无实参传递给它
    
    def get_descriptive_name(self):
        """返回整洁的汽车描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()  
    
    def read_odometer(self):
        """打印一条汽车里程的信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")
        
    def update_odometer(self, mileage):
        """
        将里程表读数设置为指定的值
        并禁止将里程表的读数往回调
        """
        if mileage >= self.odometer_reading:  #里程数必须 ≥ 当前的里程读数
            self.odometer_reading = mileage
        else:
            print("You can't roll back an odometer!")
            
    def increment_odometer(self, miles):
        """里程表读数增加指定的量"""
        self.odometer_reading += miles
#**********************以下是单独的电池类*************************#
class Battery():
    """一次模拟电动汽车电瓶的简单尝试"""
    
    def __init__(self, battery_size=70):#初始化形参的值时最好不要加空格!
        """初始化电瓶的属性"""          #在这里我们定义了一个[可选]形参battery_size
        self.battery_size = battery_size
        
    def describe_battery(self):
        """打印一条描述电池容量的信息"""
        print("This car has a " + str(self.battery_size) + "-KWh batttery.")
        
    def get_range(self):
        """打印一条消息,指出电瓶的续航里程数"""
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:         #elif后是必须加条件的
            range = 270
            
        message = "This car can go approximately " + str(range)
        message += " miles on a full charge." #字符串的连接方式
        print(message)
#************************以下是子类****************************#    
class ElectricCar(Car):
    """电动汽车的独特之处"""
    
    def __init__(self, make, model, year):
        """
        电动汽车的独特之处
        初始化父类的属性,再初始化子类的属性
        """    
        super().__init__(make, model, year) 
        self.battery = Battery() #****直接将 Battery类作为其中的一个[方法]****#
        
#开始创建实例
my_tesla = ElectricCar('tesla', 'model s', 2016)

print(my_tesla.get_descriptive_name()) #用于返回整洁的信息
my_tesla.battery.describe_battery() 
my_tesla.battery.get_range()
【注意最后调用的时】:
get_range( )函数在Battery类里的,在ElectricCar类里已经将Battery类作为了其一个方法——self.battery = Battery( ),所以可以直接调用battery( )

Result:

2016 Tesla Model S
This car has a 70-KWh batttery.
This car can go approximately 240 miles on a full charge.


6 动手试一试 --- 冰淇淋小店

#**********************以下是餐馆的类**********************#
class Restaurant():
    """餐馆的简介"""
    
    def __init__(self, restaurant_name, cuisine_type):
        """初始化餐馆的属性name和type"""
        self.name = restaurant_name #注意后面的名称是形参 --- 这里是初始化的形参
        self.type = cuisine_type    #用self,使下面的所有方法都可使用初始化的形参
        
    def describe_restaurant(self):
        """描述餐馆的信息"""
        print(self.name.title() + " is the type of " + self.type +'.')
        
    def open_restaurant(self):
        """餐馆营业时间"""
        print(self.name.title() + " is open from 8 am to 10 PM.\n" )
#**********************下面尝试编写其子类**********************#
class IceCreamStand(Restaurant):
    """冰淇淋小店重现"""
    
    def __init__(self, restaurant_name, cuisine_type):
        """初始化父类的属性"""
        super().__init__(restaurant_name, cuisine_type) #用super()函数连接父类
        self.icecream_flavors = [
                                  'original', 
                                 'chocolate',
                                     'mocha', 
                                 'strawberry'
                                 ]
        
#现在这个子类具有了父类的所有方法和属性,让我们来增加一些方法
    def flavors(self):
        """显示冰淇淋的口味列表"""
        print("It has the following tastes icecream:")
        for icecream_flavor in self.icecream_flavors:
            print(icecream_flavor)
            
#************************下面创建实例***********************#    
restaurant = IceCreamStand('cold-drink shop', 'fruity')
#先调用父类的方法试试
restaurant.describe_restaurant()
restaurant.open_restaurant()
#下面调用子类新增的方法
restaurant.flavors()

Result:

Cold-Drink Shop is the type of fruity.
Cold-Drink Shop is open from 8 am to 10 PM.

It has the following tastes icecream:
original
chocolate
mocha
strawberry

【在初始化的时候要特别注意 】:
1.super().__init__(形参1 ,形参2)的形式 —— 与父类连接
2.子类新增方法时,要现在初始化代码下”声明“ —— self.icecream_flavors = ...
3.在使用属性时候要加self—— for icecream_flavor in self.icecream_flavors:

最后也想不起来说啥,看到的就提前祝你猪(* ̄(oo) ̄)年大吉吧!

7df9446e6c0aee5a4cea61e984bb2ad6.jpg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容