Python——模块和包

模块

Python的模块(Modules)是Python程序的重要组成部分,它们允许你将代码分解成可重用的单元。每个模块都是一个包含Python代码的文件,文件名就是模块名加上.py后缀。模块可以定义函数、类和变量,也可以包含可执行的代码。下面详细解析Python模块的几个关键方面。

1. 模块的作用

  • 代码重用:模块允许你定义一次函数、类或变量,然后在程序的其他部分或其他程序中导入并使用它们。这避免了代码的重复,提高了代码的可维护性和可重用性。
  • 命名空间管理:每个模块都有自己的命名空间,这意味着在模块内部定义的函数、类和变量名不会与其他模块中的名称冲突。这有助于避免命名冲突,并使得代码更加清晰。
  • 保持全局状态:模块也可以用来保存全局变量,这些变量在模块内被所有函数共享。然而,需要注意的是,过度使用全局变量可能会使代码难以理解和维护。

2. 模块的导入

在Python中,你可以使用import语句来导入模块。一旦模块被导入,你就可以使用模块名作为前缀来访问模块中定义的函数、类和变量。

  • 导入整个模块:使用import module_name可以导入整个模块。之后,你需要使用module_name.function_namemodule_name.class_namemodule_name.variable_name的形式来访问模块中的函数、类或变量。
  • 从模块中导入特定的部分:使用from module_name import item_name可以从模块中导入特定的函数、类或变量。之后,你可以直接使用item_name来访问它们,而不需要模块名作为前缀。此外,还可以使用from module_name import *来导入模块中的所有公开名称(尽管这种做法通常不推荐,因为它可能导致命名冲突)。
  • 将导入的模块关联为其他名字:使用import 模块名 as 关联名称,可以将模块以其他名称导入到自己的程序中,使用关联名称.函数名或者属性名,来访问导入模块中的函数、类和变量。

3. 模块的执行流程

当Python解释器遇到import语句时,它会做以下几件事:

  1. 查找模块文件:Python解释器首先在当前目录下查找具有指定名称的.py文件。如果没有找到,它会继续搜索标准库目录、第三方库目录以及通过环境变量指定的其他目录。
  2. 编译模块:如果找到了模块文件,Python解释器会将其编译成字节码(如果尚未编译)。这一步是惰性的,即只有在实际需要执行模块中的代码时才会进行编译。
  3. 执行模块代码:在编译之后,Python解释器会执行模块中的代码。如果模块代码中有顶层可执行代码(即不在任何函数或类定义中的代码),这些代码将在导入模块时执行。但是,请注意不要在模块中编写太多的顶层可执行代码,因为这可能会导致在导入模块时产生不必要的副作用。
  4. 缓存模块:为了加快后续导入的速度,Python会将已编译的模块对象存储在内存中。这意味着如果再次导入相同的模块,Python将不会重新读取和编译模块文件,而是直接使用缓存中的模块对象。

4. 自定义模块

除了Python标准库中的模块外,你还可以创建自己的模块。只需编写一个.py文件,并在其中定义所需的函数、类和变量即可。然后,你可以在其他Python程序中使用import语句来导入这个模块,并使用其中定义的内容。

5. 注意事项

  • 避免命名冲突:在编写模块时,请确保模块名不与Python标准库中的模块名冲突。此外,在模块内部定义函数、类和变量时,也应注意避免命名冲突。
  • 编写文档字符串:为你的模块、函数、类和变量编写文档字符串是一个好习惯。这有助于其他开发者理解你的代码,并了解如何使用你的模块。
  • 模块搜索路径:Python解释器会按照一定的顺序在多个目录中查找模块文件。你可以通过修改sys.path列表来添加新的搜索路径,或者通过设置环境变量来影响Python的搜索路径。

if __name__ == "__main__"

在Python中,if __name__ == "__main__": 这行代码的意图是检查当前运行的脚本是否是主程序。在Python中,每个Python模块(一个.py文件)都有一个内置的属性__name__。当模块被直接运行时,__name__ 的值被设置为 "__main__"。但是,如果模块是被导入到其他模块中的(即使用 import 语句),那么 __name__ 的值就被设置为该模块的名字(不包含.py扩展名)。

这个特性允许一个模块在被直接执行时运行一些代码,而在被导入时则不运行这些代码。这通常用于编写既可以作为脚本直接运行,又可以作为模块被其他脚本导入的Python文件。

下面是一个简单的例子来说明这一点:

# 文件名: example.py  def main():  print("Hello, World!")  if __name__ == "__main__":  main()
  • 如果你直接运行 example.py(例如,在命令行中输入 python example.py),那么 __name__ 的值将是 "__main__",因此 if __name__ == "__main__": 下的 main() 函数将被调用,你将在控制台看到输出 Hello, World!

  • 如果你从另一个Python文件中导入 example.py(使用 import example),那么 example.py 中的 __name__ 将被设置为 "example"(即模块名),if __name__ == "__main__": 下的代码将不会执行。因此,main() 函数不会被自动调用。但是,你仍然可以在导入的模块中通过 example.main() 来手动调用 main() 函数。

Python的包(Packages)是组织模块(Modules)的一种高级方式,它们允许你将相关的模块组织在一起,形成一个层次化的文件目录结构。包本质上是一个包含__init__.py文件(在Python 3.3及以后的版本中,这个文件通常是可选的,但在某些情况下仍然需要)的目录,该目录下还可以包含其他模块和子包。

包的作用

  1. 代码组织:包允许你将相关的模块组织在一起,形成一个逻辑上的单元。这有助于保持代码的整洁和可管理性。

  2. 命名空间:包为模块提供了一个额外的命名空间,这有助于避免不同包中的模块之间的命名冲突。

  3. 分发和重用:包可以作为一个整体被分发和重用。你可以将你的包上传到Python包索引(PyPI),然后其他开发者就可以通过pip等包管理工具轻松地安装和使用你的包。

包的结构

一个包通常包含以下几个部分:

  • __init__.py文件(可选,但在某些情况下需要):这个文件是包的标识,它告诉Python这个目录应该被视为一个包。在Python 3.3及以后的版本中,这个文件通常是空的,但你可以在其中编写初始化代码,这些代码将在包被导入时执行。

  • 模块文件.py文件):包中可以包含多个模块文件,这些文件定义了函数、类和变量等。

  • 子包:包还可以包含子包,即包内的目录也是包。这允许你创建层次化的包结构。

  • 包内资源:包还可以包含非Python文件,如数据文件、配置文件等。这些文件通常放在包的子目录中,并通过特定的机制(如pkg_resources模块)来访问。

包的导入

在Python中,你可以使用import语句来导入包。但是,与导入模块不同,导入包通常不会直接执行包中的代码(除非在__init__.py文件中编写了初始化代码)。相反,导入包会创建一个指向该包的命名空间的引用,你可以通过这个引用来访问包中的模块和其他内容。

  • 导入整个包:使用import package_name可以导入整个包。但是,这通常不会让你直接访问包中的模块或函数,除非你在__init__.py文件中显式地导入了它们。

  • 从包中导入模块:使用from package_name import module_name可以从包中导入特定的模块。之后,你可以直接使用模块名来访问模块中的函数、类和变量。

  • 从包中导入特定的函数或类:使用from package_name.module_name import function_name, class_name可以从包中的模块中导入特定的函数或类。

  • 使用星号(*)导入:虽然不推荐,但你可以使用from package_name import *来导入包中的所有内容(这取决于__init__.py文件中的__all__变量)。然而,这种做法可能会导致命名冲突和代码难以维护。

注意事项

  • 避免循环导入:在包的设计中,要特别注意避免循环导入的问题。循环导入是指两个或多个模块相互导入对方,这会导致Python解释器陷入无限循环中。

  • 初始化代码:在__init__.py文件中编写初始化代码时要谨慎,因为这段代码会在包被导入时执行。如果初始化代码依赖于包中的其他模块或资源,并且这些模块或资源尚未被加载,那么可能会引发问题。

  • 包分发:如果你打算将你的包分发到PyPI上,那么你需要遵循一定的规范,如编写setup.py文件、编写文档和测试等。这些步骤将帮助其他开发者安装和使用你的包。

__all__属性

在Python中,模块和包的__all__属性是一个字符串列表,用于指定当使用from ... import *语句时应该导入哪些名称(属性、函数、类等)。这有助于控制导入时的命名空间,避免无意中导入不希望公开的内部函数或变量。

模块中的__all__

当你定义一个模块时,可以显式地设置__all__列表来指定哪些名称应该被导出。如果__all__没有被定义,则使用from ... import *时,将不会导入以单下划线(_)开头的名称(这些通常被视为“私有”的),但会导入所有其他非私有名称

# example_module.py  def public_function():  """一个公共函数"""  pass  def _private_function():  """一个私有函数,不应该被导入"""  pass  __all__ = ['public_function']

在上面的例子中,只有public_function会被from example_module import *导入。

包中的__all__

对于包(包含__init__.py文件的目录),__all__可以定义在__init__.py文件中,用于控制从包级别导入时的名称。如果没有定义__all__,那么from...import * 的语法则不导入包里面的任何模块,这恰恰与模块中的__all__属性相反。

# 假设有以下包结构  
# mypackage/  
# ├── __init__.py  
# ├── module_a.py  
# └── _module_b.py  # 假设这是一个内部模块,不希望被导入  # mypackage/__init__.py  from .module_a import function_a  __all__ = ['function_a']

在这个例子中,只有function_a(从module_a.py导入),可以被from mypackage import *导入。尽管_module_b.py存在于包中,但由于它没有在__all__中列出,且以单下划线开头(通常意味着它是私有的),因此它不会被导入。

注意事项

  • 使用__all__是可选的,但它是控制from ... import *行为的一种好方法。
  • 在包中,__all__可以定义在__init__.py文件中,以控制包的公共API。
  • 如果没有定义__all__,则from ... import *会导入除以下划线开头的名称之外的所有名称。
  • 最好避免在代码中使用from ... import *,因为它会使代码的可读性和可维护性降低。相反,应该显式地导入需要的名称。

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

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

相关文章

sheng的学习笔记-AI-半监督聚类

AI目录:sheng的学习笔记-AI目录-CSDN博客 半监督学习:sheng的学习笔记-AI-半监督学习-CSDN博客 聚类:sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 均值算法:sheng的学习笔记-AI-K均值算法_k均值算法怎么算迭代两次后的最大…

突发!Runway 从 HuggingFace 及 GitHub 上删库跑路,背后有何隐情?

突发!2024年8月29日Runway 从 HuggingFace 及 GitHub 上删库跑路,背后有何隐情? 🧐 今天我们来聊一聊科技圈一则爆炸性消息:Runway ML 从 HuggingFace 和 GitHub 上删库跑路,毫无预警!这个举动…

Java大文件上传方案(vue+饿了么):秒传、断点续传、分片上传!

前言 本篇文章是基于其他文章的基础上结合自己的理解写出来的,如果哪里有问题请指出! 详细教程 秒传 1、什么是秒传 通俗的说,你把要上传的东西上传,服务器会先做MD5校验,如果服务器上有它就会进入秒传,想要不秒传&#xff0…

properties文件提示未引用

问题描述 以前用的好好的项目,今天突然打开就发现idea不识别spring配置信息显示未引用,如果config代码中引入的配置却可以高亮显示,然后输入spring相关的配置,文件是没有提示的。经过研究发现是spring相关的插件被关闭了。效果如下 解决方法 启用三个插件spring Boot,Sp…

看完这100道软件测试面试题,拿不到offer,算我输

掌握此套面试题,人手至少2份offer,绝不瞎吹!分享给大家。 一、自我介绍 二、灵活问题 1、大概说说之前公司的测试流程 2、测试报告有哪些内容? 3、如何保证用例的覆盖度? 4、什么是测试用例,什么是测试脚本&…

知识社区的小程序源码系统 界面支持万能DIY装修 带源代码包以及搭建部署教程

系统概述 知识社区的小程序源码系统是一款专为构建知识分享和交流社区而设计的强大工具。它提供了完整的源代码包,使开发者能够根据自己的需求进行定制和扩展,打造出个性化的小程序应用。 该系统的界面设计简洁大方,易于操作,同…

【JavaEE】线程安全性问题,线程不安全是怎么产生的,该如何应对

产生线程不安全的原因 在Java多线程编程中,线程不安全通常是由于多个线程同时访问共享资源而引发的竞争条件。以下是一些导致线程不安全的常见原因: 共享可变状态:当多个线程对共享的可变数据进行读写时,如果没有适当的同步机制&…

鸿蒙Next 单元测试框架——hypium

一 框架概述 单元测试框架(hypium)是HarmonyOS上的测试框架,提供测试用例编写、执行、结果显示能力,用于测试系统或应用接口。 表1 单元测试框架功能特性 二 安装使用 目前hypium以npm包的形式发布, 因此需要在Deveco Studio 工程级package.json内配…

CSS-常用属性【看这一篇就够了】

目录 前言文章 常用属性 cursor鼠标样式 outline外轮廓 border与outline的区别 overflow超出部分隐藏 overflow属性值 overflow-x和overflow-y vertical-align属性 应用案例 常用的a标签布局按钮 水平居中的轮播图按钮 产品展示效果: 小米商城菜单 前…

【C#】属性的声明

在面向对象程序设计中,属性是访问对象存储数据的首选方式。 一般不要直接公开类的变量成员,即便是get访问器和set访问器并无数据访问规则。 属性的声明 1. 完整声明 在代码中输入propfull ,并连续按两下tab键 高亮的部分是可以修改的部分,按tab键可以…

FPGA上板项目(四)——FIFO测试

目录 实验内容实验原理FIFO IP 核时序绘制HDL 代码仿真综合实现上板测试 实验内容 理解 FIFO 原理调用 FIFO IP 核完成数据读写 实验原理 FIFO:First In First Out,先入先出式数据缓冲器,用来实现数据先入先出的读写方式。可分类为同步 FI…

一个php快速项目搭建框架源码,带一键CURD等功能

介绍: 框架易于功能扩展,代码维护,方便二次开发,帮助开发者简单高效降低二次开发成本,满足专注业务深度开发的需求。 百度网盘下载 图片:

Redis 入门到精通1

一、String(字符串) 特点: 最基本的数据类型,二进制安全,可以存储任何数据,比如图片或者序列化的对象。一个 key 对应一个 value。 常用命令及示例: SET key value:设置一个键值对。…

科研绘图系列:R语言多组极坐标图(grouped polar plot)

介绍 Polar plot(极坐标图)是一种二维图表,它使用极坐标系统来表示数据,而不是像笛卡尔坐标系(直角坐标系)那样使用x和y坐标。在极坐标图中,每个数据点由一个角度(极角)和一个半径(极径)来确定。角度通常从水平线(或图表的某个固定参考方向)开始测量,而半径则是…

CannotCreateTransactionException产生原因及解决方案

CannotCreateTransactionException 是 Spring 框架中的一个异常,通常出现在使用 Spring 的事务管理器时。该异常表明事务无法创建,可能是由于与底层资源(如数据库连接)相关的问题导致的。这是一个运行时异常,通常与 Da…

MySQL 函数、约束、多表查询与事务详解

在 MySQL 数据库中,函数、约束、多表查询和事务是非常重要的概念,它们可以帮助我们更好地管理和操作数据。本文将详细介绍这些概念,并通过代码演示来帮助你更好地理解。 一、函数 MySQL 提供了许多内置函数,可以用于处理字符串、数…

【网络安全】服务基础第一阶段——第六节:Windows系统管理基础---- DNS部署与安全

计算机智能识别并用IP地址定位,例如我们想要访问一个网页,其实是只能使用这个网页的IP地址,即四位的0~255来访问,但这一串数字难以记忆,于是就有了DNS,将难以记忆的数字转化为容易记忆的域名&am…

odbc连接达梦数据库DM8

odbc连接达梦数据库DM8 1 环境介绍2 达梦数据库安装3 odbc安装3.1 查询yum 匹配的odbc安装包3.2 安装 unixODBC.x86_64 4 配置odbc4.1 查看odbc 环境信息 5 odbc连接dm8成功5.1 配置 odbcinst.ini5.2 配置 odbc.ini5.3 odbc 连接达梦数据库5.3.1 dmdba 用户使用isql5.3.2 root …

AI模型:追求全能还是专精?

OpenAI计划在秋季推出的代号为“草莓”的新AI模型,展现了从数学问题到主观营销策略等多样化处理能力,这确实是一个引人注目的全能型AI发展的里程碑。关于全能型AI是否代表未来趋势,以及相比专业型AI产品是否具有更广阔的经济市场和用户吸引力…

合宙LuatOS产品规格书——Air700EAQ

Luat Air700EAQ是合宙的LTE Cat.1bis通信模块,采用移芯EC716E平台,支持LTE 3GPP Rel.13技术。 该模块专为满足小型化、低成本需求而设计,具备超小封装和极致成本优势。 Air700EAQ支持移动双模,内置丰富的网络协议,集…