《手把手陪您学Python》44——类的导入

​在上一篇《手把手陪您学Python》43——类的继承中,我们学习了父类和子类的继承关系,同时再一次见证了__init__()方法的神奇之处。

今天,我们将介绍面向对象编程最后一部分的内容,也就是类的导入。

之前我们在《手把手陪您学Python》30——模块中介绍过模块的导入,也就是在我们的程序文件中使用其他文件中的函数。

顾名思义,类的导入就是在我们的程序文件中,通过模块的导入,使用其他文件中的类。

虽然我们上节课说过,要建立子类继承父类的属性和方法,就要在一个文件中同时包括父类和子类,而且父类要在子类之前。但是当我们创建大型项目时,会涉及大量父类和子类继承关系的定义,如果都写在一个文件中,必然会导致代码量的激增。

此时,就需要我们在当前程序文件中通过导入方式,引入其他文件中的类,特别是标准化或者是其他开发者已经编译好的类,以简化程序文件中的代码量。

这就是导入类的意义,也和导入模块中的函数的意义是一样的。这时我们对模块的认识也有了相应的扩展,模块中不仅有大量Python开发者已经编写好的函数,还有很多强大的类供我们使用。

由于导入类与导入函数的模式非常相似,所以在下面介绍类的导入时,就直接借用了当时介绍模块时导入函数的内容结构与文字描述,方便大家的前后对比。

1、创建类

要让类是可导入的,就得先创建包括类的模块。

模块是扩展名为.py的文件,包含要导入到程序中的代码。

由于Jupyter Notebook保存文件的扩展名是.ipynb,是不能够作为模块保存和导入的,所以在制作模块文件时,需要我们使用PyCharm软件编写代码和保存模块。在导入类进行使用时,可以随意使用Jupyter Notebook或PyCharm。

下面就让我们一起创建一个包含Mario和Enemy两个类的模块:

In [1]: """定义马里奥类和敌人类"""
​
        class Mario:
            def __init__(self, life, cap, name, food):
                self.life = life
                self.cap = cap
                print("{} has {} lifes.".format(name, self.life))
                print("{} has a {} cap.".format(name, self.cap))
                self.jump()
                self.eat(name, food)
                self.attack(name)
        
            def jump(self):
                print("Mario is jumping!")
        
            def attack(self,name):
                print("{} attacked an anomy!".format(name))
        
            def eat(self, name, food):
                print("Mario ate a {}!".format(food))
                print("{} became bigger!".format(name))
        
        
        class Enemy:
            number = "many"
        
            def attack(self):
                print("What a pity! Mario was killed by the enemy~~~")

将这个代码段在PyCharm中保存为mario.py(默认就是保存为.py),这就是我们创建的包含着类模块,一会儿我们会多次导入这个模块,并引入其中的类、属性、方法以及创建子类。

2、导入类的方法

导入类的方法有很多种,下面就对每种方法进行逐一的介绍。

a、导入整个模块

在mario.py所在的目录中,创建一个名为mario_a.py的文件。(如果用Jupyter Notebook创建,文件名就是mario_a.ipynb,都可以。)

使用import语句导入刚才创建的模块,就可以调用里面的类了。

为了全面展示导入类的效果和作用,在后面的示例中,对于Mario类,我们会进行继承的演示;对于Enemy类,我们会进行实例的引用。

In [2]: import mario
        
        
        class Super_Mario(mario.Mario):   # 调用模块中的Mario类创建子类
            def __init__(self, life, cap, name, food):
                super().__init__(life, cap, name, food)
        
        
        print("\n***The result form Mario:\n")
        Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")  # 将子类实例化
        
        print("\n***The result form Enemy:\n")
        enemy = mario.Enemy()   # 调用模块中的Enemy类并实例化
        print("There are {} enemies!".format(enemy.number))   # 引用类属性
        enemy.attack()   # 引用类方法

当运行这段代码时,import mario让Python打开mario.py文件,并将其中所有类都复制到当前程序中,也就实现了从其他文件或者模块调用类的目的,如果导入的类的位置在定义子类之前,也满足父类要在子类之前的要求。其语法格式为:

import 模块名

我们不需要了解这个复制、调用的过程是如何实现的,只需要知道在mario_a.py这个文件的代码中,可以使用mario.py中定义的所有类了。

要调用被导入模块中的某一特定类,需要将被导入模块的名称和要使用的类名称之间用英文句点“.”进行连接,语法格式为:

模块名.类名()

这样的语法格式,和我们之间介绍的“对象.方法()”非常类似,这也是Python程序易于编写,可读性高的一个体现。

上面的代码中,mario.Mario和mario.Enemy就是调用的mario.p中的两个函数的过程。

运行上面的程序,可以得到下面的结果:

Out[2]: ***The result form Mario:
    
        Super Mario has 30 lifes.
        Super Mario has a White cap.
        Mario is jumping!
        Mario ate a red mushroom!
        Super Mario became bigger!
        Super Mario attacked an anomy!
        
        ***The result form Enemy:
        
        There are many enemies!
        What a pity! Mario was killed by an enemy~~~

为了输出结果的美观,我们在实例化前,都增加了一个打印内容,以区分来自于模块中的不同的类。由于输出结果类似,在后面的实例中就不再展示输出结果了,大家可以自行运行程序查看输出结果。

这就是第一种导入类的方法,只需编写一条import语句,并在其中指定模块,就可以在程序中使用该模块中的所有类了。

b、导入特定函数

除了将整个模块进行导入外,还可以导入模块中的特定类,这种导入方法的语法格式为:

from 模块名 import 类名

如果用逗号“,”分隔类名,还可以根据需要,从模块中导入任意数量的函数,其语法格式为:

from 模块名 import 类名1, 类名2, 类名n

对于我们之前建立的mario.py模块,如果只想导入Mario类,可以再创建一个文件mario_b.py,并编写如下代码:

In [3]: from mario import Mario
​
     
        class Super_Mario(Mario):   # 调用模块中的Mario类创建子类,但不需要写模块名了
            def __init__(self, life, cap, name, food):
                super().__init__(life, cap, name, food)
        
        print("\n***The result form Mario:\n")
        Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")

可以看到,使用这种方法时,就不需要再使用“模块名.类名()”的语法格式了,而是像普通类一样,直接使用类名调用类就可以了。

这是因为,无论我们导入的是一个模块还是多个模块,如果我们要调用其中的类,需要使用“模块名.类名()”的格式先指定模块,再指定类,即使只导入一个模块也一样。而当我们导入指定的类时,那么就没有模块名的事了,直接调用类名就可以了。

c、使用as给函数指定别名

由于要导入的模块的类名称是已经定义好,或者说通用的,可能并不能满足于我们某一个程序的命名规则,还有可以与我们现有程序中的类名称冲突。此时,就可以使用as关键字,给我们从其他模块中调用的类进行命名,相当于起了个“外号”,其语法格式为:

from 模块名 import 类名 as 别名

如果要导入多个类并进行重命名,就可以写为:

from 模块名 import 类名1 as 别名1, 类名2 as 别名2, 类名n as 别名n

对于之前建立的模块,我们可以再创建一个文件mario_c.py,来实现这种导入功能:

In [4]: from mario import Mario as Ma, Enemy as En
        
        
        class Super_Mario(Ma):   # 调用模块中的Mario类创建子类,但类使用的是别名
            def __init__(self, life, cap, name, food):
                super().__init__(life, cap, name, food)
        
        
        print("\n***The result form Mario:\n")
        Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")  # 将子类实例化
        
        print("\n***The result form Enemy:\n")
        enemy = En()   # 调用模块中的Enemy类并实例化,但类使用的是别名
        print("There are {} enemies!".format(enemy.number))
        enemy.attack()

我们可以看到,通过给类重命名(起别名),不仅可以解决合理命名的问题,还可以简化类的名称,便于使用。当然,简化也要在保证不影响可读性的情况下进行。

d、使用as给模块指定别名

除了给类指定别名,还可以给模块指定简化的别名,便于我们在导入整个模块,并调用类时使用,其语法格式为:

import 函数名 as 别名

当我们使用这种导入方法时,就可以在mario_d.py中使用如下代码:

In [5]: import mario as ma
        
        
        class Super_Mario(ma.Mario):   # 调用模块中的Mario类创建子类,但模块使用的是别名
            def __init__(self, life, cap, name, food):
                super().__init__(life, cap, name, food)
        
        
        print("\n***The result form Mario:\n")
        Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")
        
        print("\n***The result form Enemy:\n")
        enemy = ma.Enemy()   # 调用模块中的Enemy类并实例化,但模块使用的是别名
        print("There are {} enemies!".format(enemy.number))
        enemy.attack()

导入模块和调用类的方式和介绍的第一种方法是一样的,只不过用简化的模块名称ma代替了原模块名称。

因为在一个程序中会导入的模块远比其中的类要少的多,所以一般使用简化模块名称的方式,而不是简化类名称的方式来编写代码,这样既达到了简化代码的目的,也不会影响程序的可读性。

所以,这种导入方式也是Python中最为常用的导入方式,包括我们在数据分析中,就会经常用到:

import numpy as np

import pandas as pd

这样的导入模块的语句。

e、导入模块中的所有类

使用“*”可以导入模块中的所有类,然后就可以像在一个文件中写的类一样使用他们了,其语法格式为:

from 模块名 import *

最后建立一个mario_e.py的文件,编写如下代码:
 

In [6]: from mario import *
​
        
        class Super_Mario(Mario):   # 调用模块中的Mario类创建子类,但不需要写模块名称了
            def __init__(self, life, cap, name, food):
                super().__init__(life, cap, name, food)
        
        
        print("\n***The result form Mario:\n")
        Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")
        
        print("\n***The result form Enemy:\n")
        enemy = Enemy()   # 调用模块中的Enemy类并实例化,但不需要写模块名称了
        print("There are {} enemies!".format(enemy.number))
        enemy.attack()

由于导入了模块中的所有类,在程序中可以直接使用名称调用每个类,而无需再用“.”来引入了。

但是,当我们要使用不是我们自己编写的类,特别是大型模块时,最好不要采用这种导入方法。因为要导入的模块中可能包括大量我们不确认的类,其名称可能会与我们当前程序中的类名称冲突。当遇到这种重复的类名称时,Python会覆盖其中的一部分类,而不是分别导入所有的类,可能导致一些我们意料不到的结果。

所以,最好的方式还是导入整个模块,并通过模块名和类名的组合方式,调用并使用类。当然,如果需要,还可以指定模块名称,达到简化代码的目的。

以上就是通过导入模块来调用其他文件中的类的介绍,同时,我们也再一次见证了Python中强大的库的调用原理,为我们后面学习数据分析及其他Python应用奠定了基础。

至此,我们有关面向对象编程的介绍就告一段落了,虽然只有短短6篇文章的内容,但基本上把面向对象编程的主要思想、类的定义、属性、方法、继承、导入都进行了介绍。也许做不到让大家能够对面向对象编程有什么深入的认识和理解,但能够将面向对象编程的基础知识介绍给大家,能够和大家一起走进面向对象编程的大门,就已经达到目的了。

面向对象编程是一种非常先进的编程思想,特别是在一些大型项目中,往往都会采用面向对象编程的思想进行开发。如今,我们已经掌握了面向对象编程的基础知识,剩下的就是我们在日常的代码编写和项目开发的过程中的应用了。

讲到这里,不仅面向对象的内容介绍完了,我们整个Python入门部门的内容也基本结束了。非常感谢大家的支持和一路的陪伴,让我也受益良多。

下一篇,我们将会一起回顾下Python入门阶段所学的内容,为我们的Python入门做一个总结,敬请关注。

 

图片

 


感谢阅读本文!如有任何问题,欢迎留言,一起交流讨论^_^

要阅读《手把手陪您学Python》系列文章的其他篇目,请关注公众号点击菜单选择,或点击下方链接直达。

《手把手陪您学Python》1——为什么要学Python?

《手把手陪您学Python》2——Python的安装

《手把手陪您学Python》3——PyCharm的安装和配置

《手把手陪您学Python》4——Hello World!

《手把手陪您学Python》5——Jupyter Notebook

《手把手陪您学Python》6——字符串的标识

《手把手陪您学Python》7——字符串的索引

《手把手陪您学Python》8——字符串的切片

《手把手陪您学Python》9——字符串的运算

《手把手陪您学Python》10——字符串的函数

《手把手陪您学Python》11——字符串的格式化输出

《手把手陪您学Python》12——数字

《手把手陪您学Python》13——运算

《手把手陪您学Python》14——交互式输入

《手把手陪您学Python》15——判断语句if

《手把手陪您学Python》16——循环语句while

《手把手陪您学Python》17——循环的终止

《手把手陪您学Python》18——循环语句for

《手把手陪您学Python》19——第一阶段小结

《手把手陪您学Python》20——列表

《手把手陪您学Python》21——元组

《手把手陪您学Python》22——字典

《手把手陪您学Python》23——内置序列函数

《手把手陪您学Python》24——集合

《手把手陪您学Python》25——列表推导式

《手把手陪您学Python》26——自定义函数

《手把手陪您学Python》27——自定义函数的参数

《手把手陪您学Python》28——自定义函数的返回值

《手把手陪您学Python》29——匿名函数

《手把手陪您学Python》30——模块

《手把手陪您学Python》31——文件的打开

《手把手陪您学Python》32——文件的读取

《手把手陪您学Python》33——文件的关闭

《手把手陪您学Python》34——文件的写入

《手把手陪您学Python》35——数据的存储

《手把手陪您学Python》36——错误和异常处理

《手把手陪您学Python》37——程序的重构

《手把手陪您学Python》38——第二阶段小结

《手把手陪您学Python》39——面向对象

《手把手陪您学Python》40——类的定义、属性与实例化

《手把手陪您学Python》41——类的方法与实例方法

《手把手陪您学Python》42——类的魔法方法

《手把手陪您学Python》43——类的继承

For Fans:关注“亦说Python”公众号,回复“手44”,即可免费下载本篇文章所用示例语句。

亦说Python——Python爱好者的学习分享园地
 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值