Python学习(15)--包和模块

简介: Python学习(15)--包和模块 1.模块 为了更好的组织代码,以及让用户更方便的调用所提供的内置函数,Python将相关代码封装到了模块中,那么什么是模块呢?其实就是我们平时编写Python代码时写的后缀为py的文件。

Python学习(15)--包和模块

1.模块

为了更好的组织代码,以及让用户更方便的调用所提供的内置函数,Python将相关代码封装到了模块中,那么什么是模块呢?其实就是我们平时编写Python代码时写的后缀为py的文件。比如,Python为我们提供的有关字符串处理的函数就封装在string这个模块中,对应到Python中的代码文件就是string.py。

Python为我们提供模块都在安装目录下的lib文件夹下,如下:

通过截图可以看到lib文件夹下的.py文件,这些文件都是Python提供的供我们调用的模块。当然用户也可以使用自己定义的模块,如下我在我的项目文件下编写了一个模块文件,operator.py,模块名为operator,模块为我们提供了4个运算函数,分别实现运算数的加减乘除操作,operator.py的代码如下:

[python] view plain copy

  1. <span style="font-size:24px;">def add(x,y):
  2.     return x+y
  3. def subtract(x,y):
  4.     return x-y
  5. def mul(x,y):
  6.     return x*y
  7. def divide(x,y):
  8.     return x/y</span>

那么写好模块之后又如何使它呢?使用模块之前需要导入模块,导入模块方法为import 模块名。调用模块中的函数方法为:模块名.函数名。具体代码例子如下:

[python] view plain copy

  1. <span style="font-size:24px;">import operator
  2. print(operator.add(2,3))</span>

打印结果如下:

如上先导入模块operator,之后再调用模块operator为我们提供的方法add(x,y)。

下面我们来对operator.py做一些修改。如下:

[python] view plain copy

  1. <span style="font-size:24px;">def add(x,y):
  2.     return x+y
  3. def subtract(x,y):
  4.     return x-y
  5. def mul(x,y):
  6.     return x*y
  7. def divide(x,y):
  8.     return x/y
  9. print(mul(5,6))</span>

如上所示,我们在文件最后调用函数mul(x,y),并打印返回结果。然后我们再次调用operator模块,调用代码如下:

[python] view plain copy

  1. <span style="font-size:24px;">import operator
  2. print(operator.add(2,3))</span>

先看下打印结果,如下:


可以看到和之前相同的调用operator模块的代码,打印结果却和之前不一样,先打印了30,才打印出调用模块时代码执行的结果。那么打印结果30是怎么来的呢?其实这是调用模块operator执行其中的代码导致的结果。之前我们修改了operator中的代码,在最后加了一句print(mul(5,6)),在调用operator执行了这段代码,于是打印出了30。怎么证明这个30就是因为调用operator模块打印出来的呢?下面我们直接调用operator模块,并不做其他操作,只是导入模块。如下:

[python] view plain copy

  1. <span style="font-size:24px;">import operator</span>

打印结果如下:

我们只是导入operator模块就打印了30,从而以上的叙述得到证明。然而我们在调用模块时,有时候并不希望执行被调用模块中的代码,因为这最后得到的结果可能会干扰我们对主模块结果的分析。

那么如何避免正在执行的主模块在调用其他模块时,可以不用执行被调用的模块中的相关代码呢?一个比较笨的办法就是把那些代码全部删除,但是被调用的模块之前可能也是一个主模块,这样做如果之后再次用到这个模块中的代码必须得重写,比较麻烦。下面介绍利用内置属性__name__来解决这一问题。

前面我们介绍过Python为我们提供的各种内置函数,同样也为我们提供了内置属性,可以把它理解为一个Python为我们提供的一个全局变量。内置属性__name__表示当前模块的模块名,如果是正在执行的主模块,那么__name__='__main__';如果是被调用模块那么__name__=模块名 下面我们再修改下operator.py中的代码,如下:

 

[python] view plain copy

  1. def add(x,y):
  2.     return x+y
  3. def subtract(x,y):
  4.     return x-y
  5. def mul(x,y):
  6.     return x*y
  7. def divide(x,y):
  8.     return x/y
  9. print("operator-name:",__name__)

 

在最后我们添加了一句,print("operator-name:",name),即打印当前模块的内置属性__name__,主模块代码如下:

 

[python] view plain copy

  1. import operator
  2. print("main:",__name__)

打印结果如下:

可以看到当调用模块operator时,执行了我们修改之后添加的语句print("operator-name:",__name__),打印出来的模块operator的__name__属性值为'operator',即模块名。主调用模块的__name__=='__main__',可见可以通过__name__属性来区分一个模块是主模块还是被调用模块。既然能够区分两者,那么通过判断__name__属性值,如果一个模块是被调用模块的话,相关代码就不执行,修改operator.py的代码如下:

 

[python] view plain copy

  1. def add(x,y):
  2.     return x+y
  3. def subtract(x,y):
  4.     return x-y
  5. def mul(x,y):
  6.     return x*y
  7. def divide(x,y):
  8.     return x/y
  9. if __name__=='__main__':
  10.     print(mul(5,6))

 

如上通过判断operator模块的内置属性是否为"__main__",如果是则表示operator为当前正在执行的主模块,可以执行operator模块中的相关代码;否则就是被调用模块,不执行相关代码。主调用模块代码如下:

 

[python] view plain copy

  1. import operator
  2. print(operator.add(2,3))

 

执行结果如下:

 

通过打印结果可以看到,在主模块中调用operator模块时并没有执行operator模块中的相关代码,以上问题得到解决。

 2.Python中模块的调用顺序

      当我们调用一个模块时,Python会首先检查当前模块是否为用户自定义的模块,即在当前项目路径下是否存在该模块,如果没有,Python会在lib文件夹下搜索该模块,如果还没有,则报错该模块没有定义。
       下面以字符串处理函数capitalize(x)为例,这是模块str提供的一个内置函数,之前我们介绍过,功能为将字符串x首字母小写变大写。代码例子如下:

[python] view plain copy

  1. s="zhangsan"
  2. print(str.capitalize(s))

打印结果如下:

下面我们在项目路径下定义一个与Python中str模块重名的模块,str.py。在这个自定义模块str中,我们定义一个函数capitalize(x),如下:

 

[python] view plain copy

  1. def capitalize(x):
  2.     return 'hello world'

 

自定义模块str中的capitalize(x)函数很简单,只是返回一个字符串"hello world".

下面是调用这个自定义str模块的代码:

 

[python] view plain copy

  1. import str
  2. s="zhangsan"
  3. print(str.capitalize(s))

 

打印结果如下:

通过打印结果发现,Python调用的函数实质上是我们自定义模块str中的capitalize(x)函数,而不是Python中的内置函数capitalize(x),这其实与Python调用模块的顺序有关。

在Python中调用一个模块时,Python会先检查该模块是否是用户自定义的模块,如上我们自定义了一个模块str,这个模块与Python中lib文件夹下的str模块重名,可以说是因为重名,我们的自定义模块把Python中的预定义str模块给覆盖住了,所以最终调用的函数是自定义模块str中的capitalize(x)函数,这也提醒我们在自定义模块时不要与系统的预定义模块重名,以免引起不必要的麻烦。

3.包

      在Python中,包其实就是模块的集合,一个包可以包含许多模块,也可以包含其他的包。对应的文件结构就是,一个文件夹中包含其他的文件夹或者若干的.py文件,包含的其他文件夹又可以包含其他文件夹或者若干的.py文件,是一个层层迭代的树形结构。
        下面我们来介绍下如何建一个自定义的包,如下:
         第一步,在项目路径下新建一个文件夹,文件夹的名字就是包名;
         第二步,在刚才的新建文件夹下,新建__init__.py文件,这个文件包含了包的一些信息,可以什么都不写,但必须要有;
         第三步,最后就可以在文件夹下新建其他包(文件夹),或者模块(.py文件)了。
         我使用Python集成开发环境是pycharm。可以看到文件结构如下:
         

可以看到,我们自定义了一个名为data的包,包下有一个模块food,food.py中的代码如下:

 

[python] view plain copy

  1. def eat(x):
  2.     print('I like to eat',x)

 

新建完包及包内模块后,那么如何调用模块中为我们提供的功能函数呢?

方法有三种。

方法一:

 

[python] view plain copy

  1. import data.food
  2. data.food.eat('rice')

 

方法一,先导入模块,再调用模块中的函数;导入模块的方式为,包名.模块名,如data.food;调用函数的方式为包名.模块名.函数名,如data.food.eat("rice")。

打印结果如下:

方法二:

 

[python] view plain copy

  1. import data.food as food
  2. food.eat('apple')

 

有时候我们在引入一个模块的时候,由于包的层层嵌套的问题,被引入模块可能要经过很多个包才能被被导入,比如data.fooddata.likefood.food,引入food这个模块经过了data,fooddata,likefood多个包,在调用模块food提供的函数时,也要写这么一大串,程序写起来很不方便,可读性也比较差。为了方便,我们可以为被导入模块起一个别名,如上import data.food as food 就是为被导入模块data.food起别名为food,调用函数的方法为模块别名.函数,如food.eat("apple"),程序打印结果如下:

方法三:

 

[python] view plain copy

  1. from data.food import eat
  2. eat('barbecue')

 

有时候为了方便调用模块为我们提供的函数,也可以直接把函数引入,引入方法为from 包名.模块名 import 函数名,如from data.food import eat;这样就可以直接调用函数,而不需要在函数之前指定包名或模块名.更加方面可读.代码打印结果如下:

以上就是引入模块的三种方法,熟练使用它们可以方便高效的编写代码.

下一节我们将介绍正则表达式,敬请期待。

原文地址http://www.bieryun.com/2341.html

相关文章
|
7月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
835 7
|
7月前
|
存储 Java 数据处理
(numpy)Python做数据处理必备框架!(一):认识numpy;从概念层面开始学习ndarray数组:形状、数组转置、数值范围、矩阵...
Numpy是什么? numpy是Python中科学计算的基础包。 它是一个Python库,提供多维数组对象、各种派生对象(例如掩码数组和矩阵)以及用于对数组进行快速操作的各种方法,包括数学、逻辑、形状操作、排序、选择、I/0 、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等。 Numpy能做什么? numpy的部分功能如下: ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。 线性代数、随机数生成以及傅里叶变换功能。 用于集成由C、C++
569 2
|
7月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
426 1
|
7月前
|
算法 Java Docker
(Python基础)新时代语言!一起学习Python吧!(三):IF条件判断和match匹配;Python中的循环:for...in、while循环;循环操作关键字;Python函数使用方法
IF 条件判断 使用if语句,对条件进行判断 true则执行代码块缩进语句 false则不执行代码块缩进语句,如果有else 或 elif 则进入相应的规则中执行
1169 1
|
7月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
550 0
|
7月前
|
JSON 算法 API
Python中的json模块:从基础到进阶的实用指南
本文深入解析Python内置json模块的使用,涵盖序列化与反序列化核心函数、参数配置、中文处理、自定义对象转换及异常处理,并介绍性能优化与第三方库扩展,助你高效实现JSON数据交互。(238字)
592 4
|
7月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
685 0
|
7月前
|
XML JSON 数据处理
超越JSON:Python结构化数据处理模块全解析
本文深入解析Python中12个核心数据处理模块,涵盖csv、pandas、pickle、shelve、struct、configparser、xml、numpy、array、sqlite3和msgpack,覆盖表格处理、序列化、配置管理、科学计算等六大场景,结合真实案例与决策树,助你高效应对各类数据挑战。(238字)
902 0
|
Python
项目依赖的python包requirements.txt文件的生成与安装
项目依赖的python包requirements.txt文件的生成与安装
1766 0
|
Python Windows
Python分发包安装pip3
Python分发包安装pip3
352 0

推荐镜像

更多