薛钦亮的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是在什么路径下搜索模块的呢?

  1. 当前目录
  2. 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的一点思考

这个文件的特殊之处有两点:

  1. 在包引入的时候自动执行
  2. 导入时,默认只导入__all__定义的模块

因此,这个文件成为构建一个可用的包必不可少的文件,如果缺少了这个文件,包只能叫做模块的集合,各模块之间还是松散的,调用时需要手动去调用每个模块。有了__init__.py,可以统一调用包中的各个模块,还可以在导入包的时候做一些必要的初始化的工作。

三、写在最后

本次的内容,新手掌握时以学会调用包和模块为主,开发包和模块是熟练之后需要做的事情。
Python自身不够强大,强大的是无数的前辈用掉了无数根头发换来的各种好用的包,因此,让我们站在前人的肩膀上,开始快乐地python编程吧。

下一篇博客内容预告:常见python包的介绍

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛钦亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值