大师兄的Python学习笔记(三): 模块和包

大师兄的Python学习笔记(二): 面向对象和类
大师兄的Python学习笔记(四): Python的内置函数

一、模块(Module)

1. 关于模块

1)什么是模块

  • 模块就是以.py结尾的Python文件。
  • 一个模块就是一个.py文件。

2)为什么需要模块

  • 从文件级别来组织程序,方便管理。
  • 可以将相关的代码放在一起,代码逻辑感更强。
  • 方便别人和自己重复利用代码。
  • 当做命名空间使用,避免命名冲突。
<模块名>.<成员名>
例1:module.var
例2:module.function()

3)如何定义模块

  • 模块就是一个普通文件,所以任何代码可以直接书写,
  • 模块能定义函数,类和变量,模块里也能包含可执行的代码。
2. 使用模块
  • 使用模块就是在模块外调用模块的内容。
  • 使用模块需要使用import指令

1)import <模块名>

  • 导入一个模块。
  • 用<模块名>.<成员名>调用模块内容。
# moduleA.py - 模块1
>>>name = 'moduleA'
>>>def funcA():
>>>    print('Here in funcA.')

# moduleB.py - 模块2
>>>import moduleA # 导入moduleA
>>>print(moduleA.name) # 调用了moduleA中的变量
'moduleA'
>>>moduleA.funcA()  # 调用了moduleA中的函数
'Here in funcA.'

2)import <模块名1>, <模块名2>

  • 导入多个模块。
  • 用<模块名>.<成员名>调用模块内容。
# moduleA.py - 模块1
>>>name = 'moduleA'
>>>def funcA():
>>>    print('Here in funcA.')

# moduleB.py - 模块2
>>>name = 'moduleB'
>>>def funcB():
>>>    print('Here in funcB.')

# moduleC.py - 模块3
>>>import moduleA, moduleB # 导入moduleA和moduleB
>>>print(moduleA.name) # 调用了moduleA中的变量
'moduleA'
>>>moduleA.funcA()  # 调用了moduleA中的函数
'Here in funcA.'
>>>print(moduleB.name) # 调用了moduleB中的变量
'moduleB'
>>>moduleB.funcB()  # 调用了moduleB中的函数
'Here in funcB.'

3)import <模块名> as <自定义名称>

  • 导入模块并自己给它起个名字。
  • 用<自定义名称>.<成员名>调用模块内容。
# moduleA.py - 模块1
>>>name = 'moduleA'
>>>def funcA():
>>>    print('Here in funcA.')

# moduleB.py - 模块2
>>>import moduleA as AAA # 导入moduleA并改名叫AAA
>>>print(AAA.name) # 调用了moduleA中的变量
'moduleA'
>>>AAA.funcA()  # 调用了moduleA中的函数
'Here in funcA.'

4)from <模块名> import <成员名>

  • 导入模块中某个成员。
  • 可以直接用成员名访问,也可以使用<模块名>.<成员名>访问。
  • 如果成员名和本地变量名冲突,则使用最后一个定义的。
# moduleA.py - 模块1
>>>name = 'moduleA'
>>>def funcA():
>>>    print('Here in funcA.')

# moduleB.py - 模块2
>>>from moduleA import name,funcA # 导入moduleA中的两个成员
>>>print(name) # 调用了moduleA中的变量
'moduleA'
>>>print(moduleA.name) # 两种调用方式都可以
'moduleA'
>>>funcA()  # 调用了moduleA中的函数
'Here in funcA.'
>>>moduleA.funcA()  # 两种调用方式都可以
'Here in funcA.'

>>>name = 'moduleB' # 新定义一个重名变量
>>>print(name)
'moduleB' 
>>>from moduleA import name
>>>print(name) # 以后定义的为准
'moduleA'

5)from <模块名> import *

  • 导入模块中的全部成员。
  • 其它的内容与4中相同。
# moduleA.py - 模块1
>>>name = 'moduleA'
>>>def funcA():
>>>    print('Here in funcA.')

# moduleB.py - 模块2
>>>from moduleA import * # 导入moduleA中的全部成员
>>>print(name) # 调用了moduleA中的变量
'moduleA'
>>>funcA()
'Here in funcA.'
3. 关于if __name__ == "__main__": 的使用
  • 在笔记(二)中,曾经提到过__name__是魔法函数,可以获得类的名称
  • 如果直接在模块中使用__name__,则获得模块的名称
>>>print(__name__) # 如果是在本模块调用,则返回__main__。
'__main__'

>>>import test
>>>test.__name__ # 如果是导入的模块,则返回模块名。
'test'
  • 所以,if __name__ == "__main__"的含义就是在执行本文件时执行后面的程序,如果是导入的模块则跳过。
  • 建议所有程序的入口都以此代码为入口。
# moduleA.py - 模块1
>>>def funcA():
>>>    print('Here in funcA.')
>>>def funcB():
>>>    print('Here in funcB.')
>>>test2()  # 被当做模块导入时也会执行执行
>>>
>>>if __name__ == "__main__": # 只在本程序执行
>>>    test1()
Here in funcA.
Here in funcB.

# moduleB.py - 模块2
>>>import moduleA # 在使用模块时,test2()直接被执行了,但是test1并没有
Here in funcB.
4. 模块的路径
  • 加载模块时,系统会在默认路径中寻找模块。
  • 默认路径包括:当前目录、Python安装路径的lib库、环境变量PYTHONPATH中指定的路径列表等
  • 可以通过sys.path查看默认路径列表
>>>import sys #导入sys包
>>>print(sys.path)
['D:\\PyCharm Community Edition 2019.1\\helpers\\pydev', 'D:\\PyCharm Community Edition 2019.1\\helpers\\third_party\\thriftpy', 'D:\\PyCharm Community Edition 2019.1\\helpers\\pydev', 'D:\\Python3.7\\python37.zip', 'D:\\Python3.7\\DLLs', 'D:\\Python3.7\\lib', 'D:\\Python3.7', 'C:\\Users\\xiaor\\PycharmProjects\\test\\venv', 'C:\\Users\\xiaor\\PycharmProjects\\test\\venv\\lib\\site-packages', 'C:\\Users\\xiaor\\PycharmProjects\\test\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.7.egg', 'C:\\Users\\xiaor\\PycharmProjects\\test\\venv\\lib\\site-packages\\pip-10.0.1-py3.7.egg', 'C:\\Users\\xiaor\\PycharmProjects\\test', 'C:/Users/xiaor/PycharmProjects/test']
  • 可以通过sys.path.append添加搜索路径
>>>import sys
>>>sys.append('d:\\test') # 添加新的搜索路径
>>>print(sys.path[-1])  # 获得list中最后一个地址
'd:\\test'
  • 模块的加载顺序:内存中已经加载好的模块 >> python内置模块 >> sys.path路径
5. .pyc和.pyo文件
  • Python解释器会在模块目录下创建__pycache__文件夹,并在文件夹内创建对应的.pyc文件
  • .pyc文件是二进制文件,目的是加快解释速度且可以隐藏源代码。
  • Python解释器在解释.py文件时,会优先查看是否有对应的最新的.pyc文件,有的话则直接加载.pyc文件。
  • 最新的.pyc文件会被优先import,并可以被单独当做模块使用。
  • .pyo文件与.pyc文件作用一致,是优化后的版本。

二、包(Package)

1. 什么是包
  • 包是用来组织管理代码的方式。
  • 包里面存放的是模块。
  • 可以将包理解为存放模块的文件夹。
  • 包含一个文件名为__init__.py的文件
2. 包的结构

/包
/------/------ __init__.py文件
/------/------ 模块1
/------/------ 模块2
/------/------ 子包
/------/------/------ __init__.py文件
/------/------/------ 子模块1
/------/------/------ 子模块2

3.关于__init__.py
  • __init__.py是一个Python文件。
  • 如果一个文件夹中包含__init__.py,Python就会把这个文件夹当做一个包。
  • 访问包会默认访问__init__.py文件。
  • 可以在__init__.py中添加导入包时默认导入的模块。
/mypackage
/------/------ __init__.py
/------/------ moduleA

#__init__.py
>>>import mypackage.moduleA # 默认导入moduleA,这里需要用全地址。

# 控制台
>>>import mypackage
>>>if __name__ == "__main__": 
>>>    print(mypackage.moduleA) # 可以直接从包中访问
<module 'mypackage.moduleA' from 'D:\\mypackage\\moduleA.py'>
  • 在导入包时,可以使用__init__.py中的内容。
/mypackage
/------/------ __init__.py

# __init__.py文件
>>>def showPosition(): # 在__init__.py中创建方法
>>>    print('here in __init__.py')

# 控制台
>>>import mypackage 
>>>mypackage.showPosition()  # 可以直接调用__init__.py中的方法
'here in __init__.py'
  • 可以在__init__.py中使用__all__定义from <包> import *时导入的模块包含哪些。
/mypackage
/------/------ __init__.py
/------/------ moduleA
/------/------ moduleB

# __init__.py文件
>>> __all__ = ['moduleA'] # 指定*只包含moduleA

# 控制台
>>>if __name__ == "__main__": 
>>>    from mypackage import *
>>>    print(moduleA) # 成功导入
<module 'mypackage.moduleA' from 'mypackage\\__init__.py'>
>>>    print(moduleB) # 导入失败
NameError: name 'moduleB' is not defined
4.包的使用

与模块相同,导入包需要使用import指令。
1)import <包名>

  • 导入一个包。
  • 可以使用__init__.py中的内容
  • 用<包名>.<模块名>调用具体的模块。
/mypackage
/------/------ __init__.py
/------/------ moduleA

# __init__
>>>import mypackage.moduleA

# moduleA
>>>def sayHi():
>>>    print('here in moduleA!')

# 控制台
>>>import mypackage # 导入包
>>>if __name__ == "__main__": 
>>>    mypackage.moduleA.sayHi() # 调用包中模块的函数
'here in moduleA!'

2)import <包名>.<模块名>

  • 导入包中的某个模块。
/mypackage
/------/------ __init__.py
/------/------ moduleA

# moduleA
>>>def sayHi():
>>>    print('here in moduleA!')

# 控制台
>>>import mypackage.moduleA # 直接导入包中的模块
>>>if __name__ == "__main__": 
>>>    moduleA.sayHi() # 调用模块的函数
'here in moduleA!'

3)import <包名> as <自定义名>

  • 自定义包的名称。
  • 注意,这种方法实际调用的是__init__.py中的内容。
/mypackage
/------/------ __init__.py
/------/------ moduleA

# __init__
>>># import mypackage.moduleA 也可以
>>>__all__ = ['moduleA']

# moduleA
>>>def sayHi():
>>>    print('here in moduleA!')

# 控制台
>>>import mypackage as mpkg # 导入包并自定义名称
>>>if __name__ == "__main__": 
>>>    mpkg.moduleA.sayHi() # 调用包中模块的函数
'here in moduleA!'

4)from <包名> import <模块名>

  • 导入包中的模块。
/mypackage
/------/------ __init__.py
/------/------ moduleA
/------/------ moduleB

>>>from mypackage import moduleA,moduleB # 导入两个模块
>>>if __name__ == "__main__": 
>>>    print(moduleA)
<module 'mypackage.moduleA' from 'D:\\mypackage\\moduleA.py'>

5)from <包名> import *

  • 导入__init__.py中的所有模块。
/mypackage
/------/------ __init__.py
/------/------ moduleA
/------/------ moduleB
/------/------ moduleC

# __init__.py
>>>__all__ = ['moduleA','moduleB']

# 控制台
>>>from mypackage import * # 导入所有__init__.py中的模块
>>>if __name__ == "__main__": 
>>>    print(moduleA)
<module 'mypackage.moduleA' from 'D:\\mypackage\\moduleA.py'>
>>>    print(moduleC) # 未包含在__init__.py中
NameError: name 'moduleC' is not defined

6)from <包名>.<模块名> import *

  • 导入包的某个模块中的所有内容。
/mypackage
/------/------ __init__.py
/------/------ moduleA

# __init__.py
>>>__all__ = ['moduleA']

# moduleA
>>>def sayHi():
>>>    print('here in moduleA')

# 控制台
>>>from mypackage.moduleA import *
>>>if __name__ == "__main__": 
>>>    sayHi() # 直接使用模块的函数名
'here in moduleA'

参考资料



本文作者:大师兄(superkmi)


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

推荐阅读更多精彩内容