当前位置: 首页 > news >正文

Python基础之:Python中的模块

简介

Python的解释环境是很好用,但是如果我们需要编写一个大型的程序的时候,解释环境就完全不够用了。这个时候我们需要将python程序保存在一个文件里。通常这个文件是以.py结尾的。

对于大型的应用程序来说,一个文件可能是不够的,这个时候我们需要在文件中引用其他的文件,这样文件就叫做模块。

模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py 。在模块内部,模块名可以通过全局变量 __name__ 获得。

模块基础

还是之前的斐波拉赫数列的例子,我们在fibo.py文件中存放了函数的实现:


def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

复制代码

编写完毕之后,我们可以在Python的解释环境中导入它:

>>> import fibo
复制代码

然后直接使用即可:

>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
复制代码

常用的函数,我们可以将其赋值给一个变量:

>>> fib = fibo.fib
>>> fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
复制代码

或者,我们在导入的时候,直接给这个模块起个名字:

>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
复制代码

或者导入模块中的函数:

>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
复制代码

每个模块都有它自己的私有符号表,该表用作模块中定义的所有函数的全局符号表。因此,模块的作者可以在模块内使用全局变量,而不必担心与用户的全局变量发生意外冲突。

执行模块

前面我们提到了可以使用import来导入一个模块,并且 __name__ 中保存的是模块的名字。

和java中的main方法一样,如果我们想要在模块中进行一些测试工作,有没有类似java中main方法的写法呢?

先看一个例子:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))
复制代码

在模块中,我们需要进行一个判断 __name__ 是不是被赋值为 "__main__"

我们这样来执行这个模块:

python fibo.py <arguments>
复制代码

以脚本执行的情况下,模块的 __name__ 属性会被赋值为 __main__ , 这也是例子中为什么要这样写的原因。

看下执行效果:

$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
复制代码

如果是以模块导入的话,那么将不会被执行:

>>> import fibo
>>>
复制代码

模块搜索路径

使用import导入模块的时候,解释器首先会去找该名字的内置模块,如果没找到的话,解释器会从 sys.path变量给出的目录列表里寻找。

sys.path的初始目录包括:

  • 当前目录
  • PYTHONPATH 指定的目录
  • 安装的默认值

dir

要想查看模块中定义的内容,可以使用dir函数。

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
复制代码

上面的例子列出了当前模块中定义的内容,包括变量,模块,函数等。

注意, dir() 不会列出内置函数和变量的名称。如果你想要这些,它们的定义是在标准模块 builtins 中。

我们可以给dir加上参数,来获取特定模块的内容:

>>> import builtins
>>> dir(builtins)  
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
 'zip']
复制代码

java中有package的概念,用来隔离程序代码。同样的在Python中也有包。

我们看一个Python中包的例子:

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...
复制代码

上面我们定义了4个包,分别是sound,sound.formats, sound.effects, sound.filters。

注意,如果是包的话,里面一定要包含 __init__.py 文件。

__init__.py 可以是一个空文件,也可以执行包的初始化代码或设置 __all__ 变量。

当导入的时候, python就会在 sys.path 路径中搜索该包。

包的导入有很多种方式,我们可以导入单个模块:

import sound.effects.echo
复制代码

但是这样导入之后,使用的时候必须加载全名:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
复制代码

如果不想加载全名,可以这样导入:

from sound.effects import echo
复制代码

那么就可以这样使用了:

echo.echofilter(input, output, delay=0.7, atten=4)
复制代码

还可以直接导入模块中的方法:

from sound.effects.echo import echofilter
复制代码

然后这样使用:

echofilter(input, output, delay=0.7, atten=4)
复制代码

如果一个包里面的子包比较多,我们可能会希望使用 * 来一次性导入:

 from sound.effects import * 
复制代码

那么如何去控制到底会导入effects的哪一个子包呢?

我们可以在 __init__.py 中定义一个名叫 __all__ 的列表,在这个列表中列出将要导出的子包名,如下所示:

__all__ = ["echo", "surround", "reverse"]
复制代码

这样from sound.effects import * 将导入 sound 包的三个命名子模块。

如果没有定义 __all__from sound.effects import * 语句 不会 从包 sound.effects 中导入所有子模块到当前命名空间;它只会导入包 sound.effects

包的相对路径

Import 可以指定相对路径,我们使用 . 来表示当前包, 使用 .. 来表示父包。

如下所示:

from . import echo
from .. import formats
from ..filters import equalizer

相关文章:

  • CSS -- 10. 移动WEB开发之rem布局
  • 2022年第三届MathorCup高校数学建模挑战赛——大数据竞赛 赛道B 北京移动用户体验影响因素研究 问题二建模方案及代码实现详解
  • 测试人不得不知的 HTTP 状态码知识
  • 【十分钟学懂Linux操作系统】
  • 【Java基础知识复盘】Java概述篇
  • Stm32标准库函数6——f103 PWM 电调(50Hz)
  • 不喜欢现在的工作,如何成功转行?
  • 腾讯天美Java程序员月均20万!掌握这个后,也太香了....
  • 网络ping不通,试试这8招
  • 密码改造技术路径大比拼--“免”改造太理想,“重”改造太复杂,“易”改造是王道
  • Docker镜像的原理
  • APS排产帮助面板制造厂商进行计划调整
  • 口罩后,那些被“优化”的程序员都去哪儿了?
  • 为什么你的程序跑不满CPU?——简单聊聊多核多线程
  • 使用windows系统给C盘分盘
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • DataBase in Android
  • Go 语言编译器的 //go: 详解
  • IndexedDB
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Java反射-动态类加载和重新加载
  • node和express搭建代理服务器(源码)
  • oldjun 检测网站的经验
  • Python学习之路16-使用API
  • Spring Cloud中负载均衡器概览
  • spring security oauth2 password授权模式
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • windows-nginx-https-本地配置
  • windows下使用nginx调试简介
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 前端性能优化--懒加载和预加载
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 如何合理的规划jvm性能调优
  • 详解NodeJs流之一
  • 学习JavaScript数据结构与算法 — 树
  • 原生 js 实现移动端 Touch 滑动反弹
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • !!Dom4j 学习笔记
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #QT(串口助手-界面)
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • ${ }的特别功能
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (06)金属布线——为半导体注入生命的连接
  • (33)STM32——485实验笔记
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (NSDate) 时间 (time )比较
  • (SpringBoot)第七章:SpringBoot日志文件
  • (编译到47%失败)to be deleted
  • (非本人原创)史记·柴静列传(r4笔记第65天)