Python基础-6 模块和包

6.模块和包

模块modules

在之前的程序里,你可能用过类似from math import pi的语句来导入变量或函数。这其实就是在使用模块

模块:Python将程序存入一个文件,可在解释器中运行。这个文件就是模块

模块中的语句可以导入(import)到其他Python程序中。

使用模块的好处:模块化,每个模块写相关的功能;避免文件过长和混乱。

创建模块

新建一个文件(文件名为模块名.py),在文件里写程序。

举个例子:创建一个和三角形相关的模块:

新建文件tri_f.py,然后在里面写入:

import math

print("tri_f 模块 开始")

def edge_length(a, b, c):
    """返回三边长度之和"""
    return a + b + c

def area(a, b, c):
    """返回三角形面积"""
    p = (a + b + c) / 2
    s = math.sqrt(p * (p - a) * (p - b) * (p - c))
    return s

print("tri_f 模块 结束")

然后保存(Ctrl+s)。这样模块就创建好了。

使用模块

使用模块通过import语句导入模块中的变量定义、函数等可执行语句等。

例,使用模块tri.f

tri_f.py同级目录下创建test.py

注意:如果不是同级目录,解释器会找不到,需要在sys.path中添加查找路径,如

import sys sys.path.append(r'D:\PY_TEST\pythonProject\6modules') #替换为自己的目录

a, b, c = 3, 4, 5
# 从模块导入特定函数
from tri_f import area   # 从tri_f模块导入函数area的定义
print(area(a, b, c))   # 然后就可以使用函数area,计算三角形面积了

# 导入模块
import tri_f                 #导入 tri_f模块
print(tri_f.area(a, b, c))  # 函数前面需要加上模块名

# 给模块起别名
import tri_f as tr
print(tr.area(a, b, c))

# (不推荐)从模块导入全部函数(_开头的函数除外)
from tri_f import *
print(area(a, b, c))
print(edge_length(a, b, c))

运行test.py我们得到下面结果:

tri_f 模块 开始
tri_f 模块 结束
6.0
6.0
6.0
6.0
12.0

通过import模块 ,我们不仅导入了函数,还会执行模块中的语句。

总结一下,Import的用法:

# 从模块导入特定函数
from 模块 import 函数

# 导入模块 
import 模块

# 给模块起别名
import 模块 as 别名

# (不推荐)从模块导入全部函数(_开头的函数除外)及变量
from 模块 import *

模块名__name__

你可能看到过 下面的语句:

 if __name__ == '__main__':
    print('hello')

这里的__name__实际上就是模块的名字。模块被导入时,__name__是模块的文件名。当这个模块作为主程序运行时,模块的__name__会赋值为'__main__'

import math
print('name=',__name__)

def edge_length(a, b, c):
    """返回三边长度之和"""
    return a + b + c

def area(a, b, c):
    """返回三角形面积"""
    p = (a + b + c) / 2
    s = math.sqrt(p * (p - a) * (p - b) * (p - c))
    return s

if __name__ == '__main__':
    print(area(3, 4, 5))
    print('hello')

运行tri_f.py,输出:

name= __main__
6.0
hello

运行test.py时,tri_f中的__name__就会变成模块名 tri_f,所以不会执行tri.f模块中if里的内容:

if __name__ == '__main__':
    print(area(3, 4, 5))
    print('hello')

模块详情

import语句导入模块时发生的事情:

执行模块中语句(包括定义函数等)。

注意:

!模块中的语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行(防止重复)。

!需要注意,如果有多个相同函数名,最后定义的函数会把之前的同名函数覆盖掉。

!可以用与访问模块函数一样的标记法,访问模块的全局变量modname.itemname

模块有自己的私有符号表,用作模块中所有函数全局符号表。因此,模块内全局变量不会与用户定义的全局变量发生冲突。(别纠结,命名空间在第九章类会详细说)

包package

创建包

包是装着模块的文件夹,文件夹下必须含 __init__.py 文件。

最简情况下,__init__.py 只是一个空文件,但该文件也可以执行包的初始化代码,或设置 __all__ 变量,详见下文(从包中导入*)。

sound/                          #顶层包
      __init__.py               #初始化
      formats/                  #子包,用于格式化声音
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  #子包,用于声音特效
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  #子包,用于过滤
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

使用包

从包导入与从模块导入非常类似。

  • 可以从包中导入单个模块,例如:

import sound.effects.echo

这段代码加载子模块 sound.effects.echo ,但引用时必须使用子模块的全名:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

  • (推荐)另一种导入子模块的方法是:

from sound.effects import echo

这段代码还可以加载子模块 echo不加包前缀也可以使用:

echo.echofilter(input, output, delay=0.7, atten=4)

  • Import 语句的另一种变体是直接导入所需的函数或变量:

from sound.effects.echo import echofilter

同样,这样也会加载子模块 echo,但可以直接使用函数 echofilter()

echofilter(input, output, delay=0.7, atten=4)

注意,使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。

优先查找包中定义的函数、类或变量等,未找到则假定 item 是模块,并尝试加载模块。如果仍然找不到 item,则触发 ImportError 异常。

相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。

从包中导入 *

类似模块导入*,使用 from sound.effects import * 时,该语句应该导入包的所有子模块。但是这可能会导入太多东西, 浪费时间且造成冲突。因此,使用 from sound.effects import *只会导入在__init__.py__all__变量里的模块。

__all__ = ["echo", "surround", "reverse"]

相对导入

包中含有多个子包时还可以用 import 语句的 from module import name 形式执行相对导入。这些导入语句使用前导句点表示相对导入中的当前包和父包。例如,相对于 effect包下的surround 模块,可以使用:

from . import echo
from .. import formats
from ..filters import equalizer
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容