设为首页 加入收藏

TOP

模块与包(一)
2017-09-30 14:17:58 】 浏览:7263
Tags:模块

模块

  一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

  其实import加载的模块分为四个通用类别: 

  1 使用python编写的代码(.py文件)

  2 已被编译为共享库或DLL的C或C++扩展

  3 包好一组模块的包

  4 使用C编写并链接到python解释器的内置模块

  引入导入模块的概念

  退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。

  随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用。

  导入模块

  import

  现在有一个spam.py的文件。

#spam.py
print('from the spam.py')

money=1000

def read1():
    print('spam->read1->money',money)

def read2():
    print('spam->read2 calling read')
    read1()

def change():
    global money
    money=0
spam.py

  在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句)。

  导入模块要做三件事:

  第一件事:创建名称空间,用来存放spam.py中定义的名字,
  第二件事:基于刚刚创建的名称空间来执行spam.py,
  第三件事:创建名字spam指向该名称空间,spam.名字的操作,都是以spam.py为准。

import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
 3 import spam
 4 import spam
 5 import spam
运行结果:
from the spam.py
导入多次

  sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。

  每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突。

import spam
money=1
spam.change()
print(money)

  进行上述操作money的值任然是1,spam模块里的函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看,并不会影响导入模块的名称空间。

import spam as sm#改个名字,没什么实际的影响
print(sm.money)
if file_format == 'xml':
    import xmlreader as reader
elif file_format == 'csv':
    import csvreader as reader
data=reader.read_date(filename)#不管是什么格式我只要知道reader就好了
起别名

可以用反射查看是否模块有这个属性。

print(hasattr(spam,'money'))

  from ... import...

  对比import spam,会将源文件的名称空间'spam'带到当前名称空间中,使用时必须是spam.名字的方式

而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了。

  这种导入方法需要注意几个地方,

from spam import read1
money=1000
read1()
#此时执行的read1来自spam模块,read1取得的值仍是spam里的money
#导入的函数read2,执行时需要调用read1(),仍然回到spam.py中找read1()
from spam import read2
def read1():
    print('==========')
read2()
#当前定义的名称会覆盖模块里的名称
from spam import read1
def read1():
    print('==========')
read1()
执行结果:
from the spam.py
==========
from spam import money,read1
money=100 #将当前位置的名字money绑定到了100
print(money) #打印当前的名字
read1() #读取spam.py中的名字money,仍然为1000

  这种方式也支持as。

from spam import read1 as read

  多行导入。

from spam import (read1,
                  read2,
                  money)

  from spam import * 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。

  使用__all__可以控制*的内容。

__all__=['money','read1'] #这样在另外一个文件中用from spam import *就这能导入列表中规定的两个名字

  如果spam.py中的名字前加_,即_money,则from spam import *,则_money不能被导入。

  导入的过程中修改模块是无效的,python不支持重载。

  if __name__ == '__main__':用来控制.py文件在不同的应用场景下执行不同的逻辑。

  模块的查找顺序是:内存中已经加载的模块(sys.modules)->内置模块->sys.path路径中包含的模块。

  python程序可以修改sys.path,路径放到前面的优先于标准库被加载。

 import sys
 sys.path.append(r'/a/b/c/d')
 sys.path.insert(0,r'/x/y/z') #排在前的目录,优先被搜索

  注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理。

import sys
sys.path.append('module.zip')
import foo,bar

#也可以使用zip中目录结构的具体位置
sys.path.append('module.zi
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python的序列Ⅱ 下一篇maya-python 新建路径

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目