导入 python_Python基础导入类

  导入类  

04

随着你不断地给类添加功能,文件可能变得很长,即便你妥善地使用了继承亦如此。为遵循Python的总体理念,应让文件尽可能整洁。为在这方面提供帮助,Python允许你将类存储在模块中,然后在主程序中导入所需的模块。

导入单个类

1

下面来创建一个只包含Car 类的模块。这让我们面临一个微妙的命名问题:在本章中,已经有一个名为car.py的文件,但这个模块也应命名为car.py,因为它包含表示汽车的代码。我们将这样解决这个命名问题:将Car 类存储在一个名为car.py的模块中,该模块将覆盖前面使用的文件car.py。从现在开始,使用该模块的程序都必须使用更具体的文件名,如my_car.py。下面是模块car.py,其中只包含Car 类的代码:

car.py

"""一个可用于表示汽车的类"""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

在代码的第一行,我们包含了一个模块级文档字符串,对该模块的内容做了简要的描述。你应为自己创建的每个模块都编写文档字符串。

下面来创建另一个文件——my_car.py,在其中导入Car 类并创建其实例:

my_car.py

from car import Carmy_new_car = Car('audy', 'a4', 2016)print(my_new_car.get_descriptive_name())my_new_car.odometer_reading = 23my_new_car.read_odometer()

第一行的import 语句让Python打开模块car ,并导入其中的Car 类。这样我们就可以使用Car 类了,就像它是在这个文件中定义的一样。输出与我们在前面看到的一样:

2016 Audy A4This car has 23 miles on it

导入类是一种有效的编程方式。如果在这个程序中包含了整个Car 类,它该有多长呀!通过将这个类移到一个模块中,并导入该模块,你依然可以使用其所有功能,但主程序文件变得整洁而易于阅读了。这还能让你将大部分逻辑存储在独立的文件中;确定类像你希望的那样工作后,你就可以不管这些文件,而专注于主程序的高级逻辑了。

在一个模块中存储多个类

2

虽然同一个模块中的类之间应存在某种相关性,但可根据需要在一个模块中存储任意数量的类。类Battery 和ElectricCar 都可帮助模拟汽车,因此下面将它们都加入模块car.py中:

car.py

"""一个可用于表示燃油汽车和电动汽车的类"""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):        """初始化电瓶的属性"""        self.battery_size = battery_size            def describe_battery(self):        """打印一条描述"""        print("This car has a " + str(self.battery_size) + "-KWh battery.")            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):    """电动汽车的独特之处"""    def __init__(self,make,model,year):        """        初始化父类的属性        再初始化电动汽车特有的属性        """        super().__init__(make,model,year)        self.battery = Battery()

现在,可以新建一个名为my_electric_car.py的文件,导入ElectricCar 类,并创建一辆电动汽车了:

my_electric_car.py

from car import ElectricCar    my_tesla = ElectricCar('telsa','model s', 2016)print(my_tesla.get_descriptive_name())my_tesla.battery.describe_battery()my_tesla.battery.get_range()

输出与我们前面看到的相同,但大部分逻辑都隐藏在一个模块中:

2016 Telsa Model SThis car has a 70-KWh battery.This car can go approximately 240 miles on a full charge.

从一个模块中导入多个类

3

可根据需要在程序文件中导入任意数量的类。如果我们要在同一个程序中创建普通汽车和电动汽车,就需要将Car 和ElectricCar 类都导入:

from car import Car,ElectricCarmy_beetle = Car('volkswagen', 'beetle', 2016)print(my_beetle.get_descriptive_name())my_tesla = ElectricCar('tesla', 'roadster', 2016)print(my_tesla.get_descriptive_name())

从一个模块中导入多个类时,用逗号分隔了各个类。导入必要的类后,就可根据需要创建每个类的任意数量的实例。

在这个示例中,我们创建了一辆大众甲壳虫普通汽车,并创建了一辆特斯拉Roadster电动汽车:

Reloaded modules: car2016 Volkswagen Beetle2016 Tesla Roadster

导入整个模块

4

你还可以导入整个模块,再使用句点表示法访问需要的类。这种导入方法很简单,代码也易于阅读。由于创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突。

下面的代码导入整个car 模块,并创建一辆普通汽车和一辆电动汽车:

 my_cars.py

import carmy_beetle = Car('volkswagen', 'beetle', 2016)print(my_beetle.get_descriptive_name())my_tesla = ElectricCar('tesla', 'roadster', 2016)print(my_tesla.get_descriptive_name())

我们导入了整个car 模块。接下来,我们使用语法 module_name.class_name 访问需要的类。像前面一样,我们在创建了一辆大众甲壳虫汽车,并创建了一辆特斯拉Roadster汽车。

导入模块中的所有类

5

要导入模块中的每个类,可使用下面的语法:

from module_name import *

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

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

在一个模块中导入另一个模块

6

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

在这种情况下,可在前一个模块中导入必要的类。

例如,下面将Car 类存储在一个模块中,并将ElectricCar 和Battery 类存储在另一个模块中。我们将第二个模块命名为electric_car.py (这将覆盖前面创建的文件electric_car.py),并将Battery 和ElectricCar 类复制到这个模块中:

electric_car.py

"""一组可用于表示电动汽车的类"""from car import Carclass 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.")            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):    """电动汽车的独特之处"""    def __init__(self,make,model,year):        """        初始化父类的属性        再初始化电动汽车特有的属性        """        super().__init__(make,model,year)        self.battery = Battery()

 ElectricCar 类需要访问其父类Car ,因此在❶处,我们直接将Car 类导入该模块中。如果我们忘记了这行代码,Python将在我们试图创建ElectricCar 实例时引发错误。

我们还需要更新模块car ,使其包含Car 类:

car.py

"""一个可用于表示燃油汽车和电动汽车的类"""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):        """初始化电瓶的属性"""        self.battery_size = battery_size            def describe_battery(self):        """打印一条描述"""        print("This car has a " + str(self.battery_size) + "-KWh battery.")            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):    """电动汽车的独特之处"""    def __init__(self,make,model,year):        """        初始化父类的属性        再初始化电动汽车特有的属性        """        super().__init__(make,model,year)        self.battery = Battery()

现在可以分别从每个模块中导入类,以根据需要创建任何类型的汽车了:

my_cars.py

from car import Carfrom electric_car import ElectricCarmy_beetle = Car('volkswagen', 'beetle', 2016)print(my_beetle.get_descriptive_name())my_tesla = ElectricCar('tesla', 'roadster', 2016)print(my_tesla.get_descriptive_name())

我们从模块car 中导入了Car 类,并从模块electric_car 中导入ElectricCar 类。接下来,我们创建了一辆普通汽车和一辆电动汽车。这两种汽车都得以正确地创建: 

2016 Volkswagen Beetle2016 Tesla Roadster

自定义工作流程

7

正如你看到的,在组织大型项目的代码方面,Python提供了很多选项。熟悉所有这些选项很重要,这样你才能确定哪种项目组织方式是最佳的,并能理解别人开发的项目。

一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有的工作,确定一切都能正确运行后,再将类移到独立的模块中。如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。

类编码风格

你必须熟悉有些与类相关的编码风格问题,在你编写的程序较复杂时尤其如此。

类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。

对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。

可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。

需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import 语句,再添加一个空行,然后编写导入你自己编写的模块的import 语句。在包含多条import 语句的程序中,这种做法让人更容易明白程序使用的各个模块都来自何方。

本次关于类的基础知识一共分成了三个部分,大家在来看下关于类的思维导图,助于记忆。

f9cec88a83c2e8bfb27e625f4d5e3859.png

f43a0d308cec5cdf9d8be4a67ac22abd.png

Life is simple, I use Python.

即日起,关注我们,

     无论起步何处,都是Python学习者。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值