15、模块 Module 和 包 package

本文详细介绍了Python中的模块和包的概念,包括模块的作用、分类,模块的导入方式,以及dir函数的使用。重点讲解了包的组织结构,如__init__.py的重要性,以及如何通过import语句导入包和子包。还提到了模块的属性如__doc__、__file__和__name__,以及隐藏属性和dir()函数的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

绪言:

  • http://blog.youkuaiyun.com/pipisorry/article/details/43313197
  • 1. python程序由包(package)模块(module)函数组成。
  • 2. 是由一系列模块组成的集合。当不同作的模块进行按文件夹分类后再组成一个整体的库,可以称为包。为了让Python将目录当做内容包,目录中必须包含__init__.py文件,用于标识当前文件夹是一个包。最简单的情况下,只需要一个空的__init__.py文件即可。包就是一个完成特定任务的工具箱,包的作用是实现程序的重用。包导入会让模块扮演的角色更为明显,也使代码更具有可读性。
  • 3. 模块是处理某一类问题的函数和类的集合,由代码、函数和类组成。函数是一段可以重复多次调用的代码。模块把一组相关的函数或代码组织到一个文件中,一个文件即是一个模块。每个模块文件是一个独立完备的命名空间,一个模块文件不能看到其他文件定义的变量名,除非它明确地导入了那个文件,模块文件起到了最小化命名冲突的作用

1、模块

  1. 模块是一个包含有一系列数据,函数,类等组成的程序组
  2. 模块是一个文件,模块文件名通常以‘.py’结尾

2、模块的作用:

  1.  让一些相关的数据,函数,类等有逻辑的组织在一起,使逻辑结构更加清晰,
  2. 我们可以使用模块将大型程序分解为可管理的小型文件,方便管理和应用。
  3. 模块中的变量,函数和类等可提供给其他模块或程序使用,重用性强

3、模块的分类:

  1.   内置模块(builtins)在解析器的内部是可以直接使用
  2.   标准库模块,安装python时已安装可直接使用
  3.   第三方模块(通常为开源),需要自己安装
  4.   用户自己编定的模块(可以作为其他人的第三方模块)

4、模块的导入 :

  • 当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。
  • import语句搜索模块的路径顺序
  • 1、搜索程序运行时的路径(当前路径)
  • 2、sys.path提供的路径(利用这个可以查找到路径。)
  • 3、搜素内置模块
  • 注意:
  • 在模块导入时,模块所有的语句都会执行。
  • 一个模块只会被导入一次,不管你执行了多少次import。

  • 模块的重新加载:
  •   import mymod
  •   import  imp
  •   imp.reload(mymod) #重新加载mymod模块
  • 模块被导入和执行的过程:
  •   1、先搜索相关路径找模块(.py文件)
  •   2、判断是否有此模块对应的.py文件,如果.pyc文件闭.py文件新,则直接加在.pyc文件
  •   3、否则用模块.py 文件生成.pyc并加载执行。
  • pyc模块的编译:
  • mymod.py-----编译-->mymod.pyc -----解释执行--->
>>> import imp
>>> import my_module
这段代码被执行了
>>> import my_module
>>> imp.reload(my_module)
这段代码被执行了
<module 'my_module' from '.\\my_module.py'>

 

  • import 语句
  • 语法: import 模块名 [ as 模块新名1 ] ,模块名2[as 模块新名2],.........
  • 作用:将一个模块整体导入到当前模块中
  • 属性用法:模块名.属性名
  • help(obj)  可以查看模块的文档字符串
import math # 导入数学模块
import sys,os #导入sys 和 os 模块
import copy as cp #给copy起一个新的名字cp
  • from  import 语句
  • 语法:
  •  from  模块名  import  模块属性名  [as  属性名新名1],模块属性名2  [as  属性名新名2]....
  • 作用:将某模块的一个或多个属性导入到单枪模块的作用域
from math impor pi
from math import sin
from math import factorial as fac
  • from import * 语句(可能会有重名)
  • 语法: from  模块名 import *
  • 作用: 将某模块的所有属性导入到当前的模块
from math import *
s = sin(pi/2)

5、模块的一些属性

  • 模块的文档字符串:(保存在doc属性里面)
  •     模块内第一个没有赋值给任何变量的字符串的文档字符串,
  • 模块的__doc__属性:
  •    用于绑定模块文档字符串
  •   __file__属性
  •     绑定模块对应的文件路径
  •  __name__属性:
  •     用来记录模块的自身名字、
  •     作用:1、记录模块名    2、判断是否为主模块
  •     说明:1、当此模块作为主模块(也就是第一个)运行时,__name__绑定‘__main__’
  •                2、当此模块不是主模块时,__name__绑定模块名(文件名去掉.py后缀)
"""这是一个模块名字

       这个模块是干什么干什么的。
"""
def hello():
    """这是一个hello函数的名字
    
    这个模块有这样的功能。
    """
    pass

print(__file__)
print("++++++++")
print(__doc__)
print("++++++++++")
print(help(__name__))

运行结果:
C:\Users\Administrator\Documents\Aptana Studio 3 Workspace\Demo1\123.py
++++++++
这是一个模块名字

       这个模块是干什么干什么的。

++++++++++
Help on module __main__:

NAME
    __main__ - 这是一个模块名字

DESCRIPTION
    这个模块是干什么干什么的。

FUNCTIONS
    hello()
        这是一个hello函数的名字
        
        这个模块有这样的功能。

DATA
    __annotations__ = {}

FILE
    c:\users\administrator\documents\aptana studio 3 workspace\demo1\123.py


None
  • 模块的__all__列表:
  •     模块中的__all__列表是一个用来存放可导入属性的字符串列表
  •     作用:限定当用 from  xxx   import * 语句导入时,只导入__all__列表内的属性。
#__all__列表限定其他模块再用 from 模块名  import * 导入时
#只导入 __all__列表内部限定的。
__all__ = ['myfun1','myfun3','name1']
print(dir())
def myfun1():
    print('myfun1被调用')

def myfun2():
    print('myfun2被调用')

def myfun3():
    print('myfun2被调用')

name1 = 'xiaomimg'
name2 = 'xiaohong'
  • 模块的隐藏属性:
  •     模块中以‘__’开头的属性,在from  XXX import * 导入时将不被导入,通常称这些属性为隐藏属性。
'''此模块示意隐藏属性以及其用法
以‘__'开头的变量在被from xxx import *
(其它导入不算)导入时,不被导入。
'''
def f():
    print('f函数被调用')#导入

def _f():#不被导入
    print('f函数被调用')

def __f():#不被导入
    print('f函数被调用')

name = 'aa'#导入
_name = 'bbbb'#不被导入
__name = 'cccc'#不被导入

6、dir 函数

  • dir([对象])   返回一个字符串列表
  •  作用:
  •  1、如果没有参数调用,则返回当前作用域内所有变量的列表
  •  2、如果给定一个对象作为参数,则返回这个对象的所在变量(属性)列表
  •          对于一个模块,返回这个模块的全部变量
  •          对于一个类对象,返回类对象的所有变量,并递归基类对象的所有变量
  •          对于其他对象,返回所有变量、类变量和基类变量

7、包(模块包) package

  • 包是将模块以文件夹的组织形式进行分组管理的方法
  • 我们通常不会把所有的文件都存储在同一个地方。我们使用一个组织良好的目录层次结构,以方便访问。相似的文件保存在同一目录中,例如,我们可以将所有歌曲保留在“music”目录中。与此类似,Python具有用于目录的软件包和用于文件的模块。随着我们的应用程序规模越来越大,带有许多模块,我们将相似的模块放在一个包中,而将不同的模块放在不同的包中。这使项目(程序)易于管理且概念清晰。
  • 类似地,由于目录可以包含子目录和文件,因此Python程序包可以具有子程序包和模块
  • 目录必须包含一个名为 __init__.py 的文件,Python才能将其视为一个。该文件可以保留为空,但是我们通常将该程序包的初始化代码放入此文件中。
  • __init__.py  文件
  •  __init__.py 是常规包内必须存在的文件
  • __init__.py 会在包加载时被自动调用
  • 作用:1、编写此包的内容
  •              2、在内部填写包的文档字符串
  • __init__.py 内的 __all__列表:
  • 作用:用来记录此包中有哪些包或模块需要在from import *语句导入时被导入。
  • 说明:__all__列表只在from  xxx import  *语句中起作用
  • 这是一个实例。假设我们正在开发一个游戏,则可能的包和模块组织如下图所示。

  • 作用:1、将一系列模块进行分类管理,有利于访问命名冲突
  •            2、可以在需要时加载一个或部分模块,而不是全部模块

8、包的导入

  • 包的导入语法:
  •  #同模块的导入规则相同
  • import  包名   [as 包别名]
  • import  包名.模块名  [as 模块新名]
import Game.Level.start
  • from  包名 import 模块名[as  模块新名]
  • from  包名.子包名  import   模块名[as  模块新名]
  • from  包名.子包名.模块名  import  属性名 [as  属性新名]
from Game.Level import start
  • from  包名  import  *
  • from   包名.子包名  import  *
from Game.Level import *
https://www.runoob.com/python3/python3-module.html
设想一下,如果我们使用 from sound.effects import *会发生什么?
Python 会进入文件系统,找到这个包里面所有的子模块,一个一个的把它们都导入进来。
但是很不幸,这个方法在 Windows平台上工作的就不是非常好,因为Windows是一个大小写不区分的系统。
在这类平台上,没有人敢担保一个叫做 ECHO.py 的文件导入为模块 echo 还是 Echo 甚至 ECHO。
(例如,Windows 95就很讨厌的把每一个文件的首字母大写显示)而且 DOS 的 8+3 命名规则对长模块名称的处理会把问题搞得更纠结。
为了解决这个问题,只能烦劳包作者提供一个精确的包的索引了。
导入语句遵循如下规则:如果包定义文件 __init__.py 存在一个叫做 __all__ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。
作为包的作者,可别忘了在更新包之后保证 __all__ 也更新了啊。你说我就不这么做,我就不使用导入*这种用法,好吧,没问题,谁让你是老板呢。这里有一个例子,在:file:sounds/effects/__init__.py中包含如下代码:
如果 __all__ 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包sound.effects和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。
这会把 __init__.py 里面定义的所有名字导入进来。并且他不会破坏掉我们在这句话之前导入的所有明确指定的模块
通常我们并不主张使用 * 这种方法来导入模块,因为这种方法经常会导致代码的可读性降低。不过这样倒的确是可以省去不少敲键的功夫,而且一些模块都设计成了只能通过特定的方法导入。

记住,使用 from Package import specific_submodule 这种方法永远不会有错。事实上,这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。

如果在结构中包是一个子包(比如这个例子中对于包sound来说),而你又想导入兄弟包(同级别的包)你就得使用导入绝对的路径来导入。比如,如果模块sound.filters.vocoder 要使用包 sound.effects 中的模块 echo,你就要写成 from sound.effects import echo。
  • 包的相对导入:包内模块的相互导入
  •  语法:  from 相对路径包或模块import 属性或模块
  •               from 相对路径包或模块  import *
  • 说明:
  •     包的相对导入不能用于 import  xxx  语句中
  • 相对路径:
  •    ·代表当前目录
  •    ··代表上一级目录
  •    ···代表上二级目录   以此类推
  • 注:相对导入时不能超出包的外部。
from .open import hello #假设有hello这个函数
from ..Sound import play

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值