Python基础学习day5|类的创建与继承

面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。

创建和使用类

创建创建Dog

根据约定,在Python中,首字母大写的 名称指的是类。这个类定义中的括号是空的,因为我们要从空白创建这个类。

>>> class Dog():
    """一次模拟小狗的简单尝试"""
    def __int__(self,name,age):
        """初始化属性name和age"""
        self.name=name
        self.age=age
    def sit(self):
        """模拟小狗被命令时蹲下"""
        print(self.name.title()+"坐下!")
       def roll_over(self):
           """模拟小狗被命令时打滚"""
           print(self.name.title()+ " 打滚!")

输出结果:

My dog's name is Willie.
My dog is 6 years old.

方法__init__()

类中的函数称为方法 ;__init__()是一个特殊的方法,每当你根据Dog 类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
方法__init__()定义成了包含三个形参:selfnameage 。在这个方法的定义中,形参self必不可少,还必须位于其他形参的前面

根据类创建实例

可将类视为有关如何创建实例的说明。

代码示例:

my_dog = Dog('demo',18)
print(my_dog.name.title())
print(my_dog.age)

访问属性

要访问实例的属性,可使用句点表示法,即句点后加属性名。例my_dog.name表示访问属性name的值

调用方法

要调用方法,可指定实例的名称和要调用的方法,并用句点分隔它们。同上,句点后面是方法名

代码示例:

my_dog = Dog('demo', 6)
my_dog.sit()
my_dog.roll_over()

创建多个实例

my_dog = Dog('demo', 6)
you_dog = Dog('demo_go', 6)

使用类和实例

类编写好后,你的大部分时间都将花在使用根据类创建的实例上。你需要执行的一个重要任务是修改实例的属性。你可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。

Car

class Car():
    """docstring for Car"""
    def __init__(self, make,model,year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model=model
        self.year=year

    def get_name(self):
        """返回整洁的描述属性"""
        long_name=str(self.year)+'---'+self.make+'---'+self.model
        return long_name.title()

my_new_car = Car('audi','a4','2016')
print(my_new_car.get_name())

处理的结果是:

2016---Audi---A4

给属性设置默认值

类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。在有些情况下,如设置默认值时,在方法init()内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。

car类d的__init__的方法新增属性self.odometer_reading = 0,同时新增一个方法read_odometer()

def read_odometer(self): 
    # 打印一条指出汽车里程的消息 
    print("汽车的里程有:" + str(self.odometer_reading))

调用该方法:

my_car = Car('audi','A4','2016')
print(my_car.get_descript())
my_car.read_odometer()

修改属性的值

可以以三种不同的方式修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方法进行递增(增加特定的值)。

1.直接修改属性的值

代码如下:

my_new_car.odometer_reading = 23 
my_new_car.read_odometer()

有时候需要像这样直接访问属性,但其他时候需要编写对属性进行更新的方法。

2.通过方法修改属性的值

Car类新增一个update_odometer()的方法,专门用来修改属性的值。

代码如下:

def update_odometer(self,update_value):
    # 修改里程值
    self.odometer_reading = update_value

在调用的时候就很简单了:

my_new_car.update_odometer(66)
my_new_car.read_odometer()

通过方法对属性的值进行递增

递增的逻辑其实很简单,只有将之前的记录保存并且和后面传入的值进行相加操作即可。

代码如下:

def update_odometer(self,update_value):
    # 修改里程值
    self.odometer_reading += update_value

调用方法:

my_new_car.update_odometer(6)
my_new_car.read_odometer()
my_new_car.update_odometer(1)
my_new_car.read_odometer()
类事例

继承

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

子类的方法__init__()

创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。我们直接在上一节的汽车类基础上添加一个ElectricCar类,让它继承Car类。

class ElectricCar(Car):   #创建子类时,必须在括号内包含父类的名称。
    # 电动汽车
    def __init__(self,name,model,year):
        # 初始化父类的属性
        super().__init__(name,model,year)
    
# 示例化
my_car = ElectricCar('dian', 'model s', 2019)
print(my_tesla.get_descriptive())

输出结果:

2016---Tesla---Model S

super()是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用ElectricCar的父类的方法__init__(),让ElectricCar实例包含父类的所有属性。父类也称为超类(superclass)super因此而得名。

给子类定义属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。和之前的定义属性和方法的逻辑类似,不做过多的阐述。可以理解为在子类里面可以自定义一些自己需要的方法或者属性。

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("这辆车是 " + str(self.battery_size) + "-kWh 电池.")

my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_name())

my_tesla.describe_battery()

输出结果

2016---Tesla---Model S
这辆车是 70-kWh 电池.

重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。或者可以理解为在子类里面可以重写一个新的方法,重新赋值一个新的属性等。通俗的理解为:“取其精华,去其糟粕”。

将实例用作属性

使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多,属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。你可以将大 型类拆分成多个协同工作的小类。

导入类

导入单个类
为了使项目代码的可读性更加高,使用该模块的程序都必须使用更具体的文件名。例如my_car.py。导入的方法和之前类似,具体语法结构如下:

from model_name import Class_name

采用improt语句让Python打开模块car,并导入其中的Car类,剩下的就可以使用了。

导入类是一种有效的编程方式。如果在这个程序中包含了整个Car类,它该有多长呀!通过将这个类移到一个模块中,并导入该模块,你依然可以使用其所有功能,但主程序文件变得整洁而易于阅读。

在一个模块中存储多个类
也就是一个模块中可以有多个类,例如父类和子类。假设my_car.py有两个类,一个是父类Car,另一个是子类ElectricCar,那么在导入该模块时,可以选择导入某一个类。

代码示例:

from model_name import Class_name

现在就可以进行示例化或者其他的操作了。

从一个模块中导入多个类
和我们之前导入函数的时候原理一样,我们可以导入任意数量的类。导入模块多个类的时候,采用逗号拼接即可。语法如下:

from model_name import Class_name0, Class_name1

导入之后,就可根据需要创建每个类的任意数量的实例。

导入整个模块
导入整个模块的语法也特别的简单,具体如下:

import model_name

这样就可以使用整个模块的任意类。

导入模块中的所有类
导入多个就用逗号一个个区分,然后倒入所有的就用*代替。所以语法如下:

from model_name import * 

引用原文。

不推荐使用这种导入方式,其原因有二。首先,如果只要看一下文件开头的import语句,就能清楚地知道程序使用了哪些类,将大有裨益;但这种导入方式没有明确地指出你使用了模块中的哪些类。这种导入方式还可能引发名称方面的困惑。如果你不小心导入了一个与程序文件中其 他东西同名的类,将引发难以诊断的错误。这里之所以介绍这种导入方式,是因为虽然不推荐使 用这种方式,但你可能会在别人编写的代码中见到它。

需要从一个模块中导入很多类时,最好导入整个模块,并使用module_name.class_name语法来访问类。这样做时,虽然文件开头并没有列出用到的所有类,但你清楚地知道在程序的哪些地方使用了导入的模块;你还避免了导入模块中的每个类可能引发的名称冲突。

在一个模块中导入另一个模块
有时候,需要将类分散到多个模块中,以免模块太大,或在同一个模块中存储不相关的类。将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类。在这种情况下,可在前一个模块中导入必要的类。

你可能感兴趣的:(Python基础学习day5|类的创建与继承)