Python基础之模块和包

news2024/7/2 20:55:39

文章目录

  • 1 模块和包
    • 1.1 模块和包
      • 1.1.1 模块
      • 1.1.2 包
      • 1.1.3 简单使用
    • 1.2 import 语句
      • 1.2.1 import
      • 1.2.2 from … import 语句
      • 1.2.3 from … import * 语句
    • 1.4 深入模块
      • 1.4.1 模块符号表
      • 1.4.2 __name__属性
      • 1.4.3 dir() 函数
      • 1.4.4 作用域
    • 1.5 常用内置模块

1 模块和包

1.1 模块和包

1.1.1 模块

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。

模块是一个包含所有定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。

1.1.2 包

最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。

使用模块还可以避免函数名变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突
但是如果不同的人编写的模块名相同怎么办,为了避免模块名冲突,Python 又引入了按目录来组织模块的方法,称为包(Packag)。
是一种管理 Python 模块命名空间的形式,采用点模块名称。比如一个模块的名称是 A.B, 那么表示一个包 A中的子模块 B 。就好像使用模块的时候,不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。

举个例子,一个abc.py的文件就是一个名字叫abc的模块,一个xyz.py的文件就是一个名字叫xyz的模块。
现在,假设我们的abc和xyz这两个模块名字与其他模块冲突了,于是我们可以通过包来组织模块,避免冲突。方法是选择一个顶层包名,比如mycompany,按照如下目录存放:

mycompany
	__init__.py
	abc.py
	xyz.ph

引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz。

注意,每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany

在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。
目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块。
最简单的情况,放一个空的:file:__init__.py就可以了。当然这个文件中也可以包含一些初始化代码或者为 __all__变量赋值。

注意:当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。
import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,抛出一个 :exc:ImportError 异常。如果使用形如 import item.subitem.subsubitem 这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。

无论是隐式的还是显式的相对导入都是从当前模块开始的。主模块的名字永远是__main__,一个Python应用程序的主模块,应当总是使用绝对路径引用。
包还提供一个额外的属性__path__。这是一个目录列表,里面每一个包含的目录都有为这个包服务的__init__.py。可以修改这个变量,用来影响包含在包里面的模块和子包。

1.1.3 简单使用

下面是一个使用 python 标准库中模块的例子。

#!/usr/bin/python3
# 文件名: using_sys.py
'模块说明'
__author__ = '开发者名字'

import sys
 
print('命令行参数如下:')
for i in sys.argv:
   print(i)
 
print('\n\nPython 路径为:', sys.path, '\n')

执行结果如下所示:
$ python using_sys.py 参数1 参数2
命令行参数如下:
using_sys.py
参数1
参数2

Python 路径为: ['/root', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages'] 
  • import sys 引入 python 标准库中的 sys.py 模块;这是引入某一模块的方法。
  • sys.argv 是一个包含命令行参数的列表。
  • sys.path 包含了一个 Python 解释器自动查找所需模块的路径的列表。

1.2 import 语句

1.2.1 import

想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:

import module1[, module2[,... moduleN]

当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。搜索路径时一个解释器会先进行搜索的所有目录的列表。
一个模块只会被导入一次,不管你执行了多少次 import。这样可以防止导入模块被一遍又一遍地执行。
当我们使用 import 语句的时候,Python解释器是怎样找到对应的文件的呢?

这就涉及到 Python 的搜索路径,搜索路径是由一系列目录名组成的,Python解释器就依次从这些目录中去寻找所引入的模块。
这看起来很像环境变量,事实上,也可以通过定义环境变量的方式来确定搜索路径。
搜索路径是在 Python 编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在 sys 模块中的 path 变量,做一个简单的demo,在交互式解释器中,输入以下代码:

>>> import sys
>>> sys.path
['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
>>> 

sys.path 输出是一个列表,其中第一项是空串 '',代表当前目录(若是从一个脚本中打印出来的话,可以更清楚地看出是哪个目录),亦即我们执行python解释器的目录(对于脚本的话就是运行的脚本所在的目录)。
因此若在当前目录下存在与要引入模块同名的文件,就会把要引入的模块屏蔽掉。

1.2.2 from … import 语句

Python 的 from 语句可以从模块中导入一个指定的部分到当前命名空间中,语法如下:from modname import name1[, name2[, ... nameN]]
例如,要导入模块 fibo 的 fib 函数,使用如下语句:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来。

1.2.3 from … import * 语句

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

1.4 深入模块

1.4.1 模块符号表

模块除了方法定义,还可以包括可执行的代码。这些代码一般用来初始化这个模块。这些代码只有在第一次被导入时才会被执行。
每个模块有各自独立的符号表,在模块内部为所有的函数当作全局符号表来使用。
所以,模块的开发者可以放心大胆的在模块内部使用这些全局变量,而不用担心把其他用户的全局变量搞混。
从另一个方面,可以通过 modname.itemname 这样的表示法来访问模块内的函数。

模块是可以导入其他模块的。在一个模块(或者脚本,或者其他地方)的最前面使用 import 来导入一个模块,当然这只是一个惯例,而不是强制的。被导入的模块的名称将被放入当前操作的模块的符号表中。

使用 import 直接把模块内(函数,变量的)名称导入到当前操作模块。但是,这种导入的方法不会把被导入的模块的名称放在当前的字符表中(所以在这个例子里面,fibo 这个名称是没有定义的)

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

一次性的把模块中的所有(函数,变量)名称都导入到当前模块的字符表:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

这将把所有的名字都导入进来,但是那些由单一下划线(_)开头的名字不在此例。大多数情况, Python程序员不使用这种方法,因为引入的其它来源的命名,很可能覆盖了已有的定义。

1.4.2 __name__属性

一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

#!/usr/bin/python3
# Filename: using_name.py

if __name__ == '__main__':
   print('程序自身在运行')
else:
   print('我来自另一模块')
运行输出如下:

$ python using_name.py
程序自身在运行
$ python
>>> import using_name
我来自另一模块

说明: 每个模块都有一个__name__属性,当其值是__main__时,表明该模块自身在运行,否则是被引入。

1.4.3 dir() 函数

内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)  
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
 '__package__', '__stderr__', '__stdin__', '__stdout__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
 '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
 'call_tracing', 'callstats', 'copyright', 'displayhook',
 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
 'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
 'thread_info', 'version', 'version_info', 'warnoptions']

如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir() # 得到一个当前模块中定义的属性列表
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
>>> a = 5 # 建立一个新的变量 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'sys']
>>>
>>> del a # 删除变量名a
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', 'sys']

1.4.4 作用域

在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过_前缀来实现的。

正常的函数和变量名是公开的(public),可以被直接引用,比如:abc,x123,PI等;
类似 __xxx__ 这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的 __author____name__ 就是特殊变量,hello模块定义的文档注释也可以用特殊变量 __doc__ 访问,我们自己的变量一般不要用这种变量名;

类似_xxx__xxx这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc,__abc等;
之所以我们说,private函数和变量“不应该”被直接引用,而不是不能被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。

private函数或变量不应该被别人引用,那它们有什么用呢?请看例子:

def _private_1(name):
    return 'Hello, %s' % name

def _private_2(name):
    return 'Hi, %s' % name

def greeting(name):
    if len(name) > 3:
        return _private_1(name)
    else:
        return _private_2(name)

我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法,外部不需要引用的函数全部定义成 private,只有外部需要引用的函数才定义为 public

1.5 常用内置模块

点击了解 Python中常用内置模块

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1880356.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

istitle()方法——判断首字母是否大写其他字母小写

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 istitle()方法用于判断字符串中所有的单词首字母是否为大写而其他字母为小写。istitle()方法的语法格式如下: str.istitle() …

Vite: 高阶特性 Pure ESM

概述 ESM 已经逐步得到各大浏览器厂商以及 Node.js 的原生支持,正在成为主流前端模块化方案。 而 Vite 本身就是借助浏览器原生的 ESM 解析能力( type“module” )实现了开发阶段的 no-bundle ,即不用打包也可以构建 Web 应用。不过我们对于原生 ESM 的…

数据倾斜优化:Hive性能提升的核心

文章目录 1. 定义2. 数据倾斜2.1 Map2.2 Join2.3 Reduce 3. 写在最后 1. 定义 数据倾斜,也称为Data Skew,是在分布式计算环境中,由于数据分布不均匀导致某些任务处理的数据量远大于其他任务,从而形成性能瓶颈的现象。这种情况在H…

==和equals的区别(面试题)

和equals有什么区别 对于基本数据类型,比较的是值是否相等,对于引用类型则是比较的地址是否相等;对于equals来说,基本数据类型没有equals方法,对于引用类型equals比较的是引用对象是否相同 那针对以上结论&#xff0c…

RabbitMq教程【精细版一】

一、引言 模块之间的耦合度过高,导致一个模块宕机后,全部功能都不能用了,并且同步通讯的成本过高,用户体验差。 RabbitMQ引言 二、RabbitMQ介绍 MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。…

python工作目录与文件目录

工作目录 文件目录:文件所在的目录 工作目录:执行python命令所在的目录 D:. | main.py | ---data | data.txt | ---model | | model.py | | train.py | | __init__.py | | | ---nlp | | | bert.py | …

DIVE INTO DEEP LEARNING 56-60

文章目录 56 Gated Recurrent Unit(GRU)56.1 Motivation: How to focus on a sequence56.2 The concept of doors56.3 Candidate hidden state56.4 hidden state56.5 summarize56.6 QA 57 Long short-term memory network57.1 Basic concepts57.2 Long short-term memory netwo…

Linux 进程信号篇

文章目录 1. 生活中的信号2. 信号的概念3. 信号的产生3.1 系统调用3.2 软件条件3.2 异常3.3 Core和Term的区别 4. 信号的保存5. 信号的处理5.1 地址空间的进一步理解5.2 键盘输入数据的过程5.3 理解OS如何正常运行5.3.1 OS如何运行5.3.2 如何理解系统调用 5.4 内核态和用户态 6…

YOLO-V1

一、YOLO-V1整体思想与网络架构 1.1 YOLO算法整体思路解读 YOLO-V1: 经典的one-stage方法 把检测问题转化成回归问题,一个CNN就搞定了! 可以对视频进行实时检测,应用领域非常广! 核心思想: 1、预测一张图像中有哪些物…

AI大模型的崛起:第四次工业革命的前奏?

在当今这个信息爆炸的时代,人工智能(AI)大模型的崛起引起了广泛的关注和讨论。有人将其视为第四次工业革命的前奏,然而,这真的可能吗?本文将探讨这一问题,并对中国AI大模型的发展进行简要分析。…

鸿蒙开发Ability Kit(程序框架服务):【向用户申请授权】

向用户申请授权 当应用需要访问用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,应该向用户请求授权,这部分权限是user_grant权限。 当应用申请user_grant权限时,需要完成以下步骤&a…

推荐系统三十六式学习笔记:原理篇.模型融合14|一网打尽协同过滤、矩阵分解和线性模型

目录 从特征组合说起FM模型1.原理2.模型训练3.预测阶段4.一网打尽其他模型5.FFM 总结 在上一篇文章中,我们讲到了使用逻辑回归和梯度提升决策树组合的模型融合办法,用于CTR预估,给这个组合起了个名字,叫“辑度组合”。这对组合中&…

鸿蒙开发设备管理:【@ohos.multimodalInput.inputEventClient (注入按键)】

注入按键 InputEventClient模块提供了注入按键能力。 说明: 本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。本模块接口均为系统接口,三方应用不支持调用。 导入模块 import inputEventCli…

小白学webgl合集-绘制有透视颜色不一样的立方体

效果 原理 结合透视矩阵和视觉矩阵进行绘制 知识点 01透视矩阵 透视矩阵将视图空间中的坐标转换为裁剪空间中的坐标,使得更远的物体看起来更小。 function perspectiveMatrix(fov, aspect, near, far) {const f 1.0 / Math.tan(fov / 2);const nf 1 / (near …

C++旋转点坐标计算

/// 获取A点绕B点旋转P度后的新坐标/// </summary>/// <param name"Angle">角度</param>/// <param name"CirPoint">圆心坐标</param>/// <param name"MovePoint">移动点的坐标</param>/// <param…

(单机架设教程)3D剑踪

前言 今天给大家带来一款单机游戏的架设&#xff1a;3D剑踪 如今市面上的资源参差不齐&#xff0c;大部分的都不能运行&#xff0c;本人亲自测试&#xff0c;运行视频如下&#xff1a; 3D剑踪 搭建教程 此游戏架设不需要虚拟机&#xff0c; 我们先解压 “3D剑踪.zip” &…

【ArcGIS AddIn插件】【可用于全国水旱灾害风险普查】全网最强洪水淹没分析插件-基于8邻域种子搜索算法-有源淹没分析算法

最近有很多GIS小伙伴咨询我关于基于8邻域种子搜索算法的有源淹没分析插件的使用方法及原理&#xff0c;咱们通过这篇文章给大家详细介绍下这款插件的运行机制。 一、插件类型及适用版本 本插件属于ArcGIS AddIn工具条插件&#xff0c;基于ArcGIS Engine10.2.2的开发环境开发的&…

某度,网盘免费加速,复活!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 有小伙伴反馈之前如下夸克网盘脚本的加速方法失效&#xff0c;小武今天测试&#xff0c;依旧正常使用&#xff01; 百度/迅雷/夸克&#xff0c;网盘免费加速&#xff0c;已破&#xf…

最强文生图模型Stable Diffusion 3 Medium 正式开源

Stability AI 宣布 Stable Diffusion 3 Medium 现已开源&#xff0c;是 Stable Diffusion 3 系列中最新、最先进的文本生成图像 AI 模型 —— 官方声称是 “迄今为止最先进的开源模型”&#xff0c;其性能甚至超过了 Midjourney 6。 Stable Diffusion 3 Medium 模型规格参数达到…

科普文:八大排序算法(JAVA实现)+ 自制动画 (袁厨的算法小屋)

我将我仓库里的排序算法给大家汇总整理了一下&#xff0c;写的非常非常细&#xff0c;还对每个算法制作了动画&#xff0c;一定能够对大家有所帮助&#xff0c;欢迎大家阅读。另外我也对 leetcode 上面可以用排序算法秒杀的算法题进行了总结&#xff0c;会在后面的文章中进行发…