人生苦短,我爱python
接上文:薛钦亮的python教程(五)极简版Python面向对象编程
在上一次更新完博客之后,收到了小伙伴肯定的留言,真的超级暖啊,给了我莫大的动力,我会继续认真更新博客,用最认真的态度去做好这件事情。
今天本文要讲一下Python中模块和包的使用。
一、模块的定义和使用
简单理解,模块就是一个包含代码的python文件,我们可以从模块中导入类、方法、对象等。
自己定义模块的作用是更好地组织代码,让代码更好用,更好懂,使用别人的模块的作用不言而喻,就是站在前人的肩膀上编程。一定程度上可以讲,Python正是有了大量前人开发好的扩展包,才变得好用和流行。
1. 导入模块
在学习自己写模块之前,先学习一下如何导入别人的模块吧(这里所引入的有的模块其实是包,为了说明import语法,请容忍此处的不严谨)。
import语句
import modulename as shortname
我们用import语句来导入一个模块,后面可以用as关键字跟一个简称(自己随便起什么名字都好)。之后,我们可以用这个模块的名字/简称加一个点(.),来访问模块下的类、对象和方法。
看两个具体的例子:
import math
print(math.sqrt(2)) #求2的平方根
import random as rdm
print(rdm.random()) #生成随机数
from … import语句
有时候,我们不想引入整个模块(常见的原因是整个模块太大了,我们如果只用一小部分功能,可以只引入其中的一部分),可以用from … import语句来实现功能,import后面所跟的,就是我们所引入的部分。
仍然是用上面的例子:
from math import sqrt
print(sqrt(2)) #这时候只需要直接调用引用的部分,无须加模块的名称
from random import random as rd_func
print(rd_func()) #可以把这个模块改为自己任意想起的名字
from … import *语句(有冷门知识点)
这个语句是把一个模块下的所有内容 (这里不准确)导入当前的命名空间,十分粗暴,可以无须通过模块名称直接调用模块内的内容,应该尽量减少使用这种语法。
from math import *
print(sqrt(2))
print(log(2,e)) #生成以e为底2的对数
print(pi) #打印π的值
这里补充一下上文说的不准确之处:这种语法不会导入以下划线开头的类、方法和对象。一般的教程这里很少提及这一点,这个知识点可能比较冷门,但我觉得需要了解一下
搜索路径
现在有个问题,Python是在什么路径下搜索模块的呢?
- 当前目录
- sys.path所包含的路径
查看sys.path的方式为
import sys
print(sys.path)
任何包含在上述路径下的模块,都是可以被搜索到并引入的。
2. 创建模块
我们可以创建一个模块,里面包含我们常用的函数。
tools.py
'''这个模块包含常用的工具'''
def print_love():
love_list = [
' $$$$ $$$$',
' $$$$$$$ $$$$$$$',
' $$$$$$$$$$$$$$$$$',
'$$$ I love you! $$$',
' $$$$$$$$$$$$$$$$$',
' $$$$$$$$$$$$$',
' $$$$$$$$$',
' $$$$$$$',
' $$$',
]
for i in love_list:
print(i)
def show_picture(path):
from PIL import Image
import matplotlib.pyplot as plt
img = Image.open(path)
plt.imshow(img)
plt.show()
if __name__ == "__main__":
show_picture("C:\\Users\\HP\\Pictures\\python.jpeg")
print_love()
这个模块包含两个函数:print_love和show_picture。最下面的几行代码的功能是:如果该文件是直接使用的,则运行下面的代码,如果是被其他文件当作模块导入时,则不运行下面的两行代码。
我们现在可以在同一个目录下创建新文件,导入刚刚写的这个模块。
from tools import print_love
print_love()
结果为:
$$$$ $$$$
$$$$$$$ $$$$$$$
$$$$$$$$$$$$$$$$$
$$$ I love you! $$$
$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$
$$$$$$$$$
$$$$$$$
$$$
二、包的定义和使用
我们已经知道了模块其实就是一个python文件,包的定义也很简单,包就是文件夹,但该文件夹下必须存在__init__.py
文件, 这个文件在调用包的时候会自动执行,但其内容可以为空。__init__.py
用于标识当前文件夹是一个包。
别人写好的大部分是包而不是模块,原因是包的结构更加复杂,可以胜任一些复杂的功能开发,我们简单来看一下。
1. 导入包
包和模块最大的区别在于,包可以有多层结构,而模块一般只有两层结构。在导入时,语法和模块的import等语句完全相同,此处就看一个含有多层结构的包的导入吧。
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt
上面两行代码功能完全相同,都是导入matplotlib中的一个子包,叫做pyplot,并简称为plt。因此,如果导入的是包,可以用pkgname.subname的方式来调用其中的子包。
2. 创建包
我们创建一个目录,叫做manytools(假装真的有很多),里面需要包含大量的子包和模块。
假设我们已经写好了其中的内容,包含了两个(假装挺多的)文件。目前的目录结构是:
----manytools/
--------love.py
--------pic.py
如果仅仅这样,我们要怎么写代码引入这些模块呢?
import manytools.love
import manytools.pic
manytools.love.print_love()
现在的代码可以正常运行,但缺点是我们需要把文件夹下面所有模块都引入一遍,才能使用其全部功能,如果其下面还有子文件夹,要一层一层引入才可以。
如果只写一个import manytools呢?
import manytools
manytools.love.print_love()
Traceback (most recent call last):
File "c:\Users\HP\Desktop\demo\main.py", line 2, in <module>
manytools.love.print_love()
AttributeError: module 'manytools' has no attribute 'love'
如果在文件夹中加一个__init__.py
呢?在__init__.py
中可以定义一个特殊变量__all__,控制当导入包的时候,自动导入的模块有哪些。
__init__.py
__all__ = ['love','pic']
当然这样写也是等价的。
import manytools.love
import manytools.pic
现在我们可以方便地去使用这个包了。
import manytools
manytools.love.print_love()
manytools.pic.show_picture('C:/Users/HP/Pictures/python.jpeg')
3. 我对__init__.py的一点思考
这个文件的特殊之处有两点:
- 在包引入的时候自动执行
- 导入时,默认只导入__all__定义的模块
因此,这个文件成为构建一个可用的包必不可少的文件,如果缺少了这个文件,包只能叫做模块的集合,各模块之间还是松散的,调用时需要手动去调用每个模块。有了__init__.py,可以统一调用包中的各个模块,还可以在导入包的时候做一些必要的初始化的工作。
三、写在最后
本次的内容,新手掌握时以学会调用包和模块为主,开发包和模块是熟练之后需要做的事情。
Python自身不够强大,强大的是无数的前辈用掉了无数根头发换来的各种好用的包,因此,让我们站在前人的肩膀上,开始快乐地python编程吧。
下一篇博客内容预告:常见python包的介绍