python 模块与文件夹 python包和文件夹的区别_Python

Python中的模块与包可以说是最基础的概念之一了。

每一个Python开发者,不论是新手还是老鸟,在开发过程中都会和模块与包打交道。

而且现在的各种IDE工具都特别的发达,各种提示功能一应俱全。很多时候,IDE都可以帮我们自动导入包与模块。

但是便利的同时,也带来了问题,因为过于依赖IDE,可能有些写了不少代码的同学,对模块与包的一些细节还不是很清楚。

本文就带大家搞清楚,模块、包以及库的概念和一些使用细节。

01

模块与包的概念



python 模块与文件夹 python包和文件夹的区别_Python

模块、包还有库这三者之间是紧密关联的,就概念上来讲,三者存在着递进关系:

模块(Module):一个.py文件就可以看做是一个模块,其中包含了变量、函数、对象、类等。

包(Package):本质上就是文件夹,里面包含了一个或者多个模块,也可以包含其它子包。在Python3.3版本以前包中必须要有__init__.py这个文件,不然就是普通文件夹,不能称之为包。

从Python3.3 以后,__init__.py如果是空的,可以省掉了,但是还是不建议这样做。

库(Library):可看成为完成特定功能的模块与包的集合。

02

模块的基本使用



python 模块与文件夹 python包和文件夹的区别_Python

我们用案例来说明Python中模块的使用。

首先创建一个文件夹module_test,在文件夹内创建文件one.py。在one.py中写一些简单的Python代码:

num = 10 def fn():    print("num是一个变量%s" % num)

one.py就可以认定是一个模块了,其中有一个变量num和一个函数fn。

接下来我们就来使用one.py中的变量与函数。

在文件夹module_test路径下,打开python的命令行,输入命令导入one模块:

>>> import one

然后就可以使用one中的变量和函数了,但是请注意,使用的方法:

>>> numTraceback (most recent call last):    File "", line 1, in   NameError: name 'num' is not defined>>> one.num10>>> one.fn()num是一个变量10

上述例子我们可看到,使用模块中的变量与函数(以下统称模块属性),需要用 模块名.变量名 或者 模块名.函数名的方式。

如果你嫌麻烦,不想在每次使用变量和函数时还要带上模块名,可以这样做:

>>> from one import num, fn>>> num10>>> fn()num是一个变量10

使用from – import语法,可以指定从模块中导入你想要的模块属性。

有时候,模块名字会老长老长了,我们可以在导入的时候,给模块指定一个别名,这个用import-as语法就可以轻松实现了,但是请注意,给模块指定的别名可不要和其他命名冲突了。

>>> import one as O>>> O.num10>>> O.fn()num是一个变量10

同样的,从模块中导入指定属性时,也可以指定别名

>>> from one import num as N>>> N10

还有一个导入模块属性的方式,就是使用 号作为通配符,导入模块中的所有属性。

>>> from one import *>>> num10>>> fn()num是一个变量10

但是这种用法,建议慎重使用,因为可能你会导入一些意想不到的属性,和已有的命名冲突。

03

包的基本使用



python 模块与文件夹 python包和文件夹的区别_Python

接下来我们来看看包。

在module_test文件夹下,我们再创建一个package_test文件夹,里面创建两个文件__init__.py和two.py。

文件结构如下:

python 模块与文件夹 python包和文件夹的区别_python import 文件夹_05

在two.py中写一些简单的代码:

num = 20  class MyClass:     def __init__(self, name):         self.name = name             def say_hello(self):         print('Hello!我是:%s' % self.name)

然后我们在还是在module_test文件夹路径下,使用python命令行,尝试导入package_test包中的内容。

>>> import package_test as pt>>> pt.twoTraceback (most recent call last):  File "", line 1, in <module>AttributeError: module 'package_test' has no attribute 'two'

当我们直接导入了package_test,并尝试访问其中的two模块时,直接报属性错误了。所以导入包之后想直接根据包来获取其中的模块,貌似是不行的。

接下来我们换一种方式尝试下:

>>> from package_test import two>>> two.num20>>> j = two.MyClass('jack')>>> j.say_hello()Hello!我是:jack

还有一种导入包中模块的方式:

>>> import package_test.two>>> two.num20

小结一下:

当你仅仅导入了包时,你并不能直接使用包下面的模块以及模块中的属性,而是涉及到具体的层级关系,一层层的导入与访问。

当要导入包中的模块时,可以用import 包名.模块名 也可以用 from 包名 import 模块名,但如果要导入模块中的某个属性时,就只能用 from 包名.模块名 import 属性名 的形式。

例如,在本例中就不能直接写:import package_test.two.num。

04

特殊的模块__init__.py



python 模块与文件夹 python包和文件夹的区别_Python

当我们使用import package_test as pt时到底发生了什么?

我们可以做一个小测试:

>>> import package_test as pt>>> pt'package_test'

从打印的结果中我们可以看到,pt其实指向的就是package_test中的__init__.py模块!

利用Python这样的一个特性,我们可以在__init__.py中根据实际需求,写一些语句。

例如,在__init__.py中我们写如下代码:

print('hello! 你试着在import package_test') from .two import * a = 30

然后重启Python命令行,并执行如下命令:

>>> import package_test as pthello! 你试着在import package_test>>> pt.num20>>> pt.a30>>> rose = pt.MyClass('rose')>>> rose.say_hello()Hello!我是:rose

从打印结果中我们可以看得很清楚,当我们import package_test as pt之后,__init__.py中的print语句被执行了。

同时由于在__init__.py中,from .two import * 语句将

two.py模块中的所有属性都导入了,所以我们可以直接根据pt包名,来访问two.py模块中的属性。

而__init__.py中自带的属性a,也可以根据导入的包名,直接访问到。

用好__init__.py模块,可以让我们的项目结构更加的清晰,使用起来更方便。

05

import的一些细节



python 模块与文件夹 python包和文件夹的区别_Python

本文的最后,我们探讨下import的一些细节:

1. import模块时,会执行模块文件中的语句

还是以我们这个项目结构为例:

python 模块与文件夹 python包和文件夹的区别_python import 文件夹_05

  • 当import package_test 时,会执行__init__.py文件
  • 当 from package_test import two时, 会执行__init__.py 和 two.py文件
  • 当 from package_test.two import num时, 也会执行__init__.py 和 two.py文件

这个大家可以自己在模块中写一些print语句打印信息来验证一下。

2. python的导入机制,会避免重复import

例如,重启一下命令行,先后两次导入package_test包,

>>>import package_testhello! 你试着在import package_test>>>import package_test

你会发现,只打印了一次 ' hello! 你试着在import package_test' ,

这是因为在执行导入时,Python会首先检查待导入的模块是否在当前已有模块之中,如果有则跳过import,来避免重复的导入。

3. 可通过sys模块中的modules属性,查看当前的模块导入情况

>>> import sys>>> sys.modules

sys.modules以字典的形式记录导入模块的信息,键是模块名,值是模块文件所在路径。

我们可以通过这个属性,来判断模块是否已经被导入



python 模块与文件夹 python包和文件夹的区别_python import 文件夹_09

END