Python模块
一、模块概述
- 命名空间
由于在Python中一切皆为对象(Object), 想要好好理解Module和Package,一定要先理解Namespace的概念。 所谓Namespace,是指标示符的可见范围。对于Python而言,常见的Namespace主要有以下几种
- Build-in Namespace (内建命名空间)
- Global Namespace (全局命名空间)
- Local Namespace (局部命名空间)
有了命名空间的概念,可以有效的解决函数或者是变量重名的问题。不同的命名空间中允许出现相同的函数名或者 是变量名。它们彼此之间不会相互影响,例如在Namespace A和B中同时有一个名为var的变量,对A.var赋值并不 会改变B.var的值。
- 为什么使用模块? 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越难以维护
- 模块概述 为了编写可维护性的代码,我们会把很多函数进行分组,分别放到不同的文件里去。这样,每个文件包含的代码就相对较少,大多数编程语言都是采用这种方式来组织代码的,在python中,一个.py文件就称之为一个模块 其中定义的所有函数或者是变量都属于这个Module。这个Module 对于所有函数而言就相当于一个全局的命名空间。而每个函数又都有自己局部的命名空间。
- 优点
- 提高了代码的可维护性
- 提高了代码的复用度,编写代码不必从零开始,当一个模块编写完成,就可以在其他地方引用
- 引用其他模块,包含python内置模块和第三方模块
- 避免函数名和变量名等命名的冲突
- 模块分类
- 标准库模块
- 第三方模块
- 自定义模块
二、使用标准库中的模块
time
import time
now = time.strftime("%Y-%m-%d %H:%M:%S") # 获取当前时间
print(now)
random
import random
random_num = random.randrange(3) # 返回012的随机数
print(random_num)
三、使用自定义模块
新建一个名为speak.py文件
# speak.py
'''
This is only a test module
'''
name = 'zutuanxue_com'
age = 18
def speak():
print("zutuanxue_com is a very good man!")
import 语句
- 作用 导入模块/包
- 格式 import module1[, module2[, module3[, ……]]] import module1 as 别名[, module2[, module3[, ……]]] 起别名
- 注意 一个模块只会被导入一次,不管你执行了多少次import,有效的防止导入模块被一次次的执行
- 使用模块中的内容 module.方法/类/变量
不起别名实例
>>> import speak # 导入speak模块
>>> speak.name # 获取模块speak中name的值
zutuanxue_com
>>> speak.age # 获取模块speak中age的值
18
>>> speak.speak() # 调用模块中speak方法
zutuanxue_com is a very good man!
>>> print speak.__doc__ # 获取模块说明
This is only a test module
起别名实例
<span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> speak <span class="hljs-keyword">as</span> s <span class="hljs-comment"># 导入speak模块 并起别名为s</span>
<span class="hljs-meta">>>> </span>s.name <span class="hljs-comment"># 获取模块speak中name的值</span>
zutuanxue_com
<span class="hljs-meta">>>> </span>s.age <span class="hljs-comment"># 获取模块speak中age的值</span>
<span class="hljs-number">18</span>
<span class="hljs-meta">>>> </span>s.speak() <span class="hljs-comment"># 调用模块中speak方法</span>
zutuanxue_com <span class="hljs-keyword">is</span> a very good man!
<span class="hljs-meta">>>> </span><span class="hljs-keyword">print</span> s.__doc__ <span class="hljs-comment"># 获取模块说明</span>
This <span class="hljs-keyword">is</span> only a test module
from … import 语句
- 作用 从模块中导入一些指定的部分
- 格式 from module import name1[, name2[, name3[, ……]]]
实例
<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> speak <span class="hljs-keyword">import</span> name,age,speak <span class="hljs-comment"># 从speak模块导入 name,age,speak</span>
<span class="hljs-meta">>>> </span>name <span class="hljs-comment"># 获取模块speak中name的值</span>
zutuanxue_com
<span class="hljs-meta">>>> </span>age <span class="hljs-comment"># 获取模块speak中age的值</span>
<span class="hljs-number">18</span>
<span class="hljs-meta">>>> </span>speak() <span class="hljs-comment"># 调用模块中speak方法</span>
zutuanxue_com <span class="hljs-keyword">is</span> a very good man!
from … import * 语句
- 概述 将模块中所有非下划线开头的成员都导入
- 作用 把一个模块中所有的内容全部导入当前命名空间
- 格式 from modulename import *
- 注意 不应该过多使用,很可能造成变量名的冲突
实例
<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> speak <span class="hljs-keyword">import</span> * <span class="hljs-comment"># 会将speak模块中非下划线开头的成员都导入当前命名空间中</span>
<span class="hljs-meta">>>> </span>name <span class="hljs-comment"># 获取模块speak中name的值</span>
zutuanxue_com
<span class="hljs-meta">>>> </span>age <span class="hljs-comment"># 获取模块speak中age的值</span>
<span class="hljs-number">18</span>
<span class="hljs-meta">>>> </span>speak() <span class="hljs-comment"># 调用模块中speak方法</span>
zutuanxue_com <span class="hljs-keyword">is</span> a very good man!
四、__all__
接口暴露
概述
代码中是不提倡用 from xxx import *
的写法的,但是在 console 调试的时候图个方便还是很常见的。如果一个模块 spam
没有定义 __all__
,执行 from spam import *
的时候会将 spam
中非下划线开头的成员都导入当前命名空间中,这样当然就有可能弄脏当前命名空间。如果显式声明了 __all__
,import *
就只会导入 __all__
列出的成员。如果 __all__
定义有误,列出的成员不存在,还会明确地抛出异常,而不是默默忽略。
格式
__all__ = ["name1", "name2"...]
作用
Python不像 Ruby 或者 Java,Python 没有语言原生的可见性控制,而是靠一套需要大家自觉遵守的”约定“下工作。比如下划线开头的应该对外部不可见。同样,__all__
也是对于模块公开接口的一种约定,比起下划线,__all__
提供了暴露接口用的”白名单“。一些不以下划线开头的变量(比如从其他地方 import
到当前模块的成员)可以同样被排除出去。
新建test_all.py
# test_all.py
'''
This is only a test __all__ module
'''
__all__ = ["name", "speak"] # 排除了 age
name = 'zutuanxue_com'
age = 18
def speak():
print("zutuanxue_com is a very good man!")
五、模块循环引用
概述
出现循环引用其实就是模块之间发生了相互依赖,A依赖B,B依赖A,这样他们直接相互依赖,引用的时候就会出现者循环引用(交叉引用)
现象
有两个模块moduleA 和 moduleB
moduleA.py
from moduleB import b
def a():
print('我是A模块的a方法')
moduleB.b()
def c():
print('我是A模块的c方法')
if __name__ == '__main__':
a()
moduleB.py
<span class="hljs-keyword">from</span> moduleA <span class="hljs-keyword">import</span> c
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">b</span><span class="hljs-params">()</span>:</span>
print(<span class="hljs-string">'我是B模块的b方法'</span>)
c()
导入的实质
导入其实是要将 被导入模块所有的顶格代码都执行一遍,遇到函数和类的定义会作申明 如果b模块中有这么一句
print(<span class="hljs-string">'我是B模块'</span>)
你在a模块impot b时就会 执行 print(‘bbb’)这一句 回到循环引用中,首先导入B,进入B中,发现B中又导入了A又回到A中,但是A又导入B这就形成了循环引用
解决方式1(直接导入模块名,通过模块调用其中的函数)
moduleA.py
import moduleB
def a():
print('我是A模块的a方法')
moduleB.b()
def c():
print('我是A模块的c方法')
if __name__ == '__main__':
a()
moduleB.py
<span class="hljs-keyword">import</span> moduleA
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">b</span><span class="hljs-params">()</span>:</span>
print(<span class="hljs-string">'我是B模块的b方法'</span>)
moduleA.c()
解决方式2(使用延迟导入(lazy import))
内部导入
<span class="hljs-string">"""
moduleB.py
"""</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">b</span><span class="hljs-params">()</span>:</span>
<span class="hljs-keyword">from</span> moduleA <span class="hljs-keyword">import</span> c
print(<span class="hljs-string">'我是B模块的b方法'</span>)
c()
六、__name__
属性
- 概述 每个模块都有一个__name__属性,当其值为“main”时表明该模块自身在运行,否则是被当做模块导入,此时值为模块的名字
实例
# speak.py
'''
This is only a test module
'''
name = 'zutuanxue_com'
age = 18
def speak():
print("zutuanxue_com is a very good man!")
if __name__ == '__main__':
speak()
__name__
作用
模块就是一个可执行的python文件,一个模块被另一个模块导入,想让模块中的某一段代码不执行,可以使用__name__
属性来使程序隐藏该段代码,当自身执行时在执行该块代码。一般作为判断是否是作为主运行文件
扩展
以后主要用于程序入口使用(项目启动文件中使用)
"""
Main.py
"""
def main():
pass
if __name__ == '__main__':
main()
七、包
需求
如果不同的人编写的模块名相同怎么办?
解决
为了避免模块名的冲突,python又引入了按目录来组织模块的方法,称为包(package)
特点
引入包以后,只要顶层包名不与别人冲突, 那么所有的模块都不会与别人冲突
注意
每个包目录下都会有一个名为__init__.py
的文件,说明这个目录是个python包,还可以导出包中的内容
建包
新建文件夹名称为lucky_package文件夹
目录结构
project/
lucky_package/
__init__.py # 声明lucky_package为一个包
speak.py # 模块speak
test.py # 用于测试lucky_package包的使用
实现 方式一 通过pycharm直接创建Python包 选择模块 -> New -> Python Package
输入包名
点击OK
- 方式二 手动创建
- 模块 -> New -> Directory
- 输入 lucky_package
- 点击OK
- lucky_package -> New -> Python File
- 输入文件名称为
__init__.py
- 点击 OK
包内创建模块
speak.py
<span class="hljs-comment"># speak.py </span>
<span class="hljs-string">'''
This is only a test module
'''</span>
name = <span class="hljs-string">'zutuanxue_com'</span>
age = <span class="hljs-number">18</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">speak</span><span class="hljs-params">()</span>:</span>
print(<span class="hljs-string">"zutuanxue_com is a very good man!"</span>)
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
speak()
使用
test.py
第一种导入方式使用
>>> from lucky_package import speak # 从zutuanxue_com_package包导入speak模块
>>> speak.name # 获取模块speak中name的值
zutuanxue_com
>>> speak.age # 获取模块speak中age的值
18
>>> speak.speak() # 调用模块中speak方法
zutuanxue_com is a very good man!
导包重命名
<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> lucky_package <span class="hljs-keyword">import</span> speak <span class="hljs-keyword">as</span> s <span class="hljs-comment"># 从zutuanxue_com_package包导入speak模块并重命名为s</span>
<span class="hljs-meta">>>> </span>s.name <span class="hljs-comment"># 获取模块speak中name的值</span>
zutuanxue_com
第二种导入方式
>>> from lucky_package.speak import name,age,speak # 从lucky_package包speak模块导入 name,age,speak
>>> name # 获取模块speak中name的值
zutuanxue_com
>>> age # 获取模块speak中age的值
18
第三种导入方式
>>> from lucky_package.speak import * # 从lucky_package包speak模块导入 所有成员
>>> name # 获取模块speak中name的值
zutuanxue_com
>>> age # 获取模块speak中age的值
18
第四种导入方式
>>> import lucky_package.speak # 导入lucky_package里speak包
>>> lucky_package.speak.name # 获取name的值
zutuanxue_com
第五种导入方式
import lucky_package.speak as s # 导入lucky_package里speak包 s.name # 获取name的值 zutuanxue_com
填充包__init__.py
代码
方式一 在init.py中 导入模块
__init__.py
from . import speak
使用
<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> lucky_package <span class="hljs-keyword">import</span> speak <span class="hljs-comment"># 导入lucky_package里speak包</span>
<span class="hljs-meta">>>> </span>speak.name <span class="hljs-comment"># 获取name的值</span>
zutuanxue_com
方式二
在init.py中 导入模块所有成员
__init__.py
from .speak import *
使用
<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> lucky_package <span class="hljs-keyword">import</span> * <span class="hljs-comment"># 导入lucky_package里speak包</span>
<span class="hljs-meta">>>> </span>name <span class="hljs-comment"># 获取name的值</span>
zutuanxue_com
注意
不建议这样使用方式
相关文章
- Python-基础04-数据类型
- 最受欢迎的8个Python框架,满足你的各类需求「建议收藏」
- Python人员信息管理系统(当期末作业)
- Python爬取抖音无水印版短视频
- python线性回归算法「建议收藏」
- Python一键生成国庆渐变头像
- python大数据分析实例-用Python整合的大数据分析实例
- Python笔记 第三章
- 用Python的turtle库画太极图
- python小波变换 wavedec2函数 各个返回值详解「建议收藏」
- Python脚本
- Python计算中位数_用频率直方图求中位数
- Python实现智能停车场车牌识别计费系统
- python lasso回归分析_解析python实现Lasso回归「建议收藏」
- python格式化转换_Python进制转换format格式化[通俗易懂]
- python encode和decode函数说明[通俗易懂]
- python进制转换函数-Python中进制转换函数的使用
- python 进制转换[通俗易懂]
- PyAOS:大气和海洋科学Python社区
- python中bool函数_bool()函数以及Python中的示例