python笔记(16)模块

模块是组织代码、实现复用、提升开发效率的关键元素。它们如同积木块一样,构成了Python程序的基石。本

一、理解Python模块:定义与基本特性

1. 定义

模块,简单来说,就是包含Python定义和语句的文件。它可以是一个.py文件,也可以是一个目录(含有__init__.py文件),甚至是一个自定义的C扩展。模块为代码提供了封装、复用和命名空间管理的功能,使得大型项目能够以更清晰、模块化的形式进行组织。

2. 基本特性

  • 代码复用:模块允许开发者将常用功能、类或函数封装在一个单独的文件中,便于在多个地方重复使用,避免代码冗余。
  • 命名空间管理:每个模块都有自己的命名空间,通过模块导入机制,可以有效避免变量名冲突,提高代码可读性和维护性。
  • 模块化设计:模块化使程序结构清晰,易于理解和分工协作,遵循"高内聚、低耦合"的原则,有利于复杂项目的开发和管理。
  • 系统资源隔离:模块有助于将不同功能的代码隔离开来,减少全局变量的使用,降低系统间的相互影响。

二、Python模块的结构与创建

1. 模块结构

一个典型的Python模块文件通常包含以下部分:

  • 文档字符串(docstring) :位于模块文件开头,用于描述模块的功能、接口、使用方法等,可通过内置函数help()pydoc工具访问。
  • 变量定义:包括常量、数据结构等,供模块内部或外部使用。
  • 函数定义:实现特定功能的独立代码块,对外提供服务。
  • 类定义:定义对象的属性和行为,实现面向对象编程。
  • 模块级代码:在模块文件顶层执行的代码,如初始化工作、注册信号处理器等。

2. 创建模块

创建一个Python模块非常简单,只需按照上述结构编写.py文件即可。例如,创建一个名为utils.py的模块,内容如下:

python 复制代码
"""
Utils module: Provides common utility functions.

Functions:
    greeting(name: str) -> str: Returns a personalized greeting message.
"""

def greeting(name: str) -> str:
    return f"Hello, {name}!"

# ... 其他函数和类定义

三、Python模块的导入与使用

1. 导入模块

Python提供了多种导入模块的方式,包括:

  • 常规导入import module_name,直接导入整个模块,通过module_name.访问其中的成员。
  • 别名导入import module_name as alias,为模块指定别名,方便调用。
  • 从模块导入特定成员from module_name import member,直接导入模块内的某个成员,无需通过模块名引用。
  • 星号(*)导入from module_name import *,导入模块的所有成员到当前命名空间。不推荐使用,易导致命名冲突和代码不易理解。

2. 使用模块

导入模块后,即可使用其提供的变量、函数、类等资源。例如,对于上文创建的utils模块:

如想要导入模块 utils.py,需要把命令放在脚本的顶端:

python 复制代码
import utils

print(utils.greeting("Alice"))  # 输出:Hello, Alice!

# 或者使用别名导入
import utils as ut

print(ut.greeting("Bob"))  # 输出:Hello, Bob!

3. 定位模块

当你导入一个模块,Python 解析器对模块位置的搜索顺序是:

  • 当前目录
  • 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
  • 如果都找不到,Python 会察看默认路径。UNIX下,默认路径一般为 /usr/local/lib/python/

模块搜索路径存储在 system 模块的 sys.path 变量中。变量里包含当前目录,PYTHONPATH 和由安装过程决定的默认目录。

4. 命名空间和作用域

变量是拥有匹配对象的名字(标识符)。命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。

一个 Python 表达式可以访问局部命名空间和全局命名空间里的变量。如果一个局部变量和一个全局变量重名,则局部变量会覆盖全局变量。

每个函数都有自己的命名空间。类的方法的作用域规则和通常函数的一样。

Python 会智能地猜测一个变量是局部的还是全局的,它假设任何在函数内赋值的变量都是局部的。

因此,如果要给全局变量在一个函数里赋值,必须使用 global 语句。

global VarName 的表达式会告诉 Python, VarName 是一个全局变量,这样 Python 就不会在局部命名空间里寻找这个变量了。

例如,我们在全局命名空间里定义一个变量 money。我们再在函数内给变量 money 赋值,然后 Python 会假定 money 是一个局部变量。然而,我们并没有在访问前声明一个局部变量 money,结果就是会出现一个 UnboundLocalError 的错误。取消 global 语句的注释就能解决这个问题。

python 复制代码
 
Money = 2000
def AddMoney():
   # 想改正代码就取消以下注释:
   #global Money
   Money=Money+1
 
print(Money)
AddMoney()
print(Money)

'''
执行会报错如下:
Traceback (most recent call last):
  File "f:\学习\python\测试\test2.py", line 9, in <module>
    AddMoney()
    ^^^^^^^^^^
  File "f:\学习\python\测试\test2.py", line 6, in AddMoney
    Money=Money+1
          ^^^^^
UnboundLocalError: cannot access local variable 'Money' where it is not associated with a value
PS F:\学习\python\测试> 
因为money在这里是局部变量没有定义
money到底是什么呢?当你读到这行代码时,完全不知道money是什么,money是整数呢?还是字符串呢?换用更专业的术语,也就是说,变量money没有被定义。
当去掉注释后可以当做全局变量不会报错,也可以在函数里写money=0,但是外面打印出来的结果还是2000,因为局部变量不能被外面的引用

'''

四、Python标准库与第三方模块

1. Python标准库

Python自带一系列丰富的标准库模块,涵盖了网络通信、文件操作、数据处理、算法实现、系统接口等诸多领域。如ossysdatetimejsonrequests等,这些都是Python编程的强大工具箱,极大地提高了开发效率。

2. 第三方模块

除了标准库外,Python生态还拥有庞大的第三方模块库,如numpypandas用于数据分析,tensorflowpytorch用于深度学习,flaskdjango用于Web开发等。这些模块可通过pip包管理器轻松安装,极大地扩展了Python的应用范围。

3.name

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

python 复制代码
#下面代码是test2.py下的代码
if __name__ == '__main__':
    print('程序自身在运行')
else:
    print('我被其他模块导入了,执行了else代码块')

#在test2.py里执行会输出:程序自身在运行

#下面是test.py里的代码
import test2 

#执行后会输出:我被其他模块导入了,执行了else代码块

说明:

  1. 每个模块都有一个 name 属性,当其值是 'main' 时,表明该模块自身在运行,否则是被引入。
  2. namemain 底下是双下划线,是"_ _"去掉中间的空格。

4.dir()函数

会把模块下的函数都列出来

python 复制代码
import sys
print(dir(sys))

#输出如下
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', 
'__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__', '_base_executable', '_clear_type_cache', '_current_exceptions', '_current_frames', '_debugmallocstats', '_enablelegacywindowsfsencoding', '_framework', '_getframe', '_getquickenedcount', '_git', '_home', '_stdlib_dir', '_xoptions', 'addaudithook', 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix', 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth', 'getallocatedblocks', 'getdefaultencoding', 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'orig_argv', 
'path', 'path_hooks', 'path_importer_cache', 'platform', 'platlibdir', 'prefix', 'pycache_prefix', 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 
'settrace', 'stderr', 'stdin', 'stdlib_module_names', 'stdout', 'thread_info', 'unraisablehook', 'version', 
'version_info', 'warnoptions', 'winver']
相关推荐
缘友一世12 分钟前
JAVA代理模式和适配器模式
java·代理模式·适配器模式
bohu8313 分钟前
sentinel学习笔记8-系统自适应与黑白名单限流
笔记·sentinel·系统自适应·authorityslot·paramflowslot
轻浮j15 分钟前
Sentinel底层原理以及使用算法
java·算法·sentinel
it噩梦15 分钟前
springboot 工程使用proguard混淆
java·spring boot·后端
香橙薄荷心18 分钟前
学一学前沿开发语言之Python
人工智能·python
潜意识起点18 分钟前
Java数组:静态初始化与动态初始化详解
java·开发语言·python
KevinRay_20 分钟前
Numpy指南:解锁Python多维数组与矩阵运算(下)
python·矩阵·numpy·排序·文件读写
竹影卿心20 分钟前
Java连接HANA数据库
java·数据库·windows
m0_7482333626 分钟前
Python大数据可视化:基于python的电影天堂数据可视化_django+hive
python·信息可视化·django
Abelard_30 分钟前
LeetCode--347.前k个高频元素(使用优先队列解决)
java·算法·leetcode