阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Python模块

194次阅读
没有评论

共计 5447 个字符,预计需要花费 14 分钟才能阅读完成。

一、模块概述

  • 命名空间

    由于在 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

    起别名实例

    >>> import speak as s # 导入 speak 模块 并起别名为 s >>> s.name # 获取模块 speak 中 name 的值 zutuanxue_com >>> s.age # 获取模块 speak 中 age 的值 18 >>> s.speak() # 调用模块中 speak 方法 zutuanxue_com is a very good man! >>> print s.__doc__ # 获取模块说明 This is only a test module
  • from … import 语句

    • 作用

      从模块中导入一些指定的部分

    • 格式

      from module import name1[, name2[, name3[, ……]]]

    实例

    >>> from speak import name,age,speak # 从 speak 模块导入 name,age,speak >>> name # 获取模块 speak 中 name 的值 zutuanxue_com >>> age # 获取模块 speak 中 age 的值 18 >>> speak() # 调用模块中 speak 方法 zutuanxue_com is a very good man!
  • from … import * 语句

    • 概述

      将模块中所有非下划线开头的成员都导入

    • 作用

      把一个模块中所有的内容全部导入当前命名空间

    • 格式

      from modulename import *

    • 注意

      不应该过多使用,很可能造成变量名的冲突

    实例

    >>> from speak import * # 会将 speak 模块中非下划线开头的成员都导入当前命名空间中 >>> name # 获取模块 speak 中 name 的值 zutuanxue_com >>> age # 获取模块 speak 中 age 的值 18 >>> speak() # 调用模块中 speak 方法 zutuanxue_com is 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

    from moduleA import c def b(): print('我是 B 模块的 b 方法') c()
  • 导入的实质

    导入其实是要将 被导入模块所有的顶格代码都执行一遍,遇到函数和类的定义会作申明
    如果 b 模块中有这么一句

    print('我是 B 模块')

    你在 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

    import moduleA def b(): print('我是 B 模块的 b 方法') moduleA.c()
  • 解决方式 2(使用延迟导入(lazy import))

    内部导入

    """moduleB.py""" def b(): from moduleA import c print('我是 B 模块的 b 方法') 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

Python 模块

输入包名

Python 模块

点击 OK

Python 模块

  • 方式二 手动创建

    • 模块 -> New -> Directory

Python 模块

  • 输入 lucky_package

Python 模块

  • 点击 OK

Python 模块

  • lucky_package -> New -> Python File

Python 模块

  • 输入文件名称为 __init__.py

Python 模块

  • 点击 OK

Python 模块

  • 包内创建模块

    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!") if __name__ == '__main__': 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!

      导包重命名

      >>> from lucky_package import speak as s # 从 zutuanxue_com_package 包导入 speak 模块并重命名为 s >>> s.name # 获取模块 speak 中 name 的值 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

      使用

      >>> from lucky_package import speak # 导入 lucky_package 里 speak 包 >>> speak.name # 获取 name 的值 zutuanxue_com
    • 方式二

      在 init.py 中 导入模块所有成员

      __init__.py

      from .speak import *

      使用

      >>> from lucky_package import * # 导入 lucky_package 里 speak 包 >>> name # 获取 name 的值 zutuanxue_com
    • 注意

      不建议这样使用方式

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-05-26发表,共计5447字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中