PYTHON类(3)继承

编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特 殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所 有属性和方法。原有的类称为父类,而新类称为子类。子类继承了父类的 所有属性和方法,同时还可以定义自己的属性和方法。

1、子类的方法__init__()

在既有类的基础上编写新类时,通常要调用父类的方法__init__()。这 将初始化在父类__init__()方法中定义的所有属性,从而让子类包含这 些属性。

例如,下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此可在前面 创建的Car类的基础上创建新类ElectricCar。这样就只需为电动汽车特 有的属性和行为编写代码。

下面来创建ElectricCar类的一个简单版本,它具备Car类的所有功能:

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)

创建子类时,父类必须包含在当前文件中,且位于子类的前面。

定义子类时,必须在括号内指定父类的名称。

super()是一个特殊函数,让你能够调用父类的方法。这行代码让 Python调用Car类的方法__init__(),让ElectricCar实例包含这个方 法中定义的所有属性。父类也称为超类(superclass),名称super由此而来。

2016 Tesla Model S

2、给子类定义属性和方法

让一个类继承另一个类后,就可以添加区分子类和父类所需的新属性和新方法了。

下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电瓶容量,并编写一个打印电瓶描述的方法:

class Car():
    ---snip---


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()

结果:

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

对于ElectricCar类的特殊程度没有任何限制。模拟电动汽车时,可根据 所需的准确程度添加任意数量的属性和方法。如果一个属性或方法是任何 汽车都有的,而不是电动汽车特有的,就应将其加入到Car类而非 ElectricCar类中。这样,使用Car类的人将获得相应的功能,而 ElectricCar类只包含处理电动汽车特有属性和行为的代码。

3、重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,都可以进行重 写。为此,可在子类中定义一个与要重写的父类方法同名的方法。这样, Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。 假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫 无意义,因此你可能想重写它。下面演示了一种重写方式:

class ElectricCar(Car):
   —--snip---

    def fill_gas_tank(self):
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")

现在,如果有人对电动汽车调用方法fill_gas_tank(),Python将忽略 Car类中的方法fill_gas_tank(),转而运行上述代码。使用继承时,可 让子类保留从父类那里继承而来的精华,并剔除不需要的糟粕。

4、将实例用作属性

使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性 和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分 提取出来,作为一个独立的类。可以将大型类拆分成多个协同工作的小 类。 例如,不断给ElectricCar类添加细节时,我们可能发现其中包含很多专 门针对汽车电瓶的属性和方法。在这种情况下,可将这些属性和方法提取 出来,放到一个名为Battery的类中,并将一个Battery实例作为 ElectricCar类的属性:

class Car():
    ---snip---

class Battery():
    """一次模拟电动汽车电瓶的简单尝试"""

    def __init__(self, battery_size=70):
        """初始化电瓶的属性"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kwh battery.")


class ElectricCar(Car):
    """电动汽车的独特之处"""

    def __init__(self, make, model, year):
        """初始化父类的属性,再初始化电动汽车特有属性"""
        super().__init__(make,model,year)
        #self.battery_size=70
        self.battery=Battery()

    def describe_battery(self):
        """打印一条描述电瓶容量的信息"""
        print("This car has a "+str(self.battery_size)+"-kwh battery.")

    def fill_gas_tank(self):
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")


my_tesla = ElectricCar('tesla', 'model s', '2016')
print(my_tesla.get_descriptive_name())
#my_tesla.describe_battery()
my_tesla.battery.describe_battery()

输出与我们前面看到的相同:

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

这看似做了很多额外的工作,但是现在想多详细地描述电瓶都可以,且不 会导致ElectricCar类混乱不堪。下面再给Battery类添加一个方法,它 根据电瓶容量报告汽车的续航里程:

class Car():
    ---snip---


class Battery():
    ---snip---

    def get_range(self):
        """打印一条消息,指出电瓶的续航里程"""
        if self.battery_size==70:
            range=240
        elif self.battery_size==85:
            range=270

        message="This car can go approximately "+str(range)
        message+=" miles on a full charge."
        print(message)


class ElectricCar(Car):
    ---snip---

my_tesla = ElectricCar('tesla', 'model s', '2016')
print(my_tesla.get_descriptive_name())
#my_tesla.describe_battery()
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

结果:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值