比尔云BierYun--阿里云最新优惠活动
阿里云优惠码丨阿里云代金券

Python学习(15)–包和模块

Python学习(15)–包和模块http://www.bieryun.com/2341.html

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;这样就可以直接调用函数,而不需要在函数之前指定包名或模块名.更加方面可读.代码打印结果如下:

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

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

未经允许不得转载:比尔云 » Python学习(15)–包和模块
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

强烈推荐

高性能SSD云服务器ECS抗攻击,高可用云数据库RDS