拓展:包和模块

该部分为中谷教育Python视频教程的学习笔记
模块——代码封装
模块是Python组织代码的基本方式。Python的脚本都是用扩展名为py的文本文件保存,一个脚本可以单独运行,也可以导入另一个脚本中运行,当脚本被导入运行时,我们将其称为模块(module)。就是说,我们在python里写的所有代码文件都可以叫模块。
导入的时候,模块名与脚本的文件名相同,例如我们编写了一个名为items.py 的脚本,则在另外一个脚本中用import item语句来导入它。
windows环境下在python中查看安装有哪些模块

>>> import sys
>>> sys.modules

#windows环境下,导入模块方式:

>>> import os
>>> os.getcwd()
'D:\\Python33'
>>> os.chdir ('F:\eclipse\workspace\learn\extend')
>>> os.getcwd()
'F:\\eclipse\\workspace\\learn\\extend'
>>> import calculator
0.5

#首先定位python的工作目录os.getcwd()
#然后改为当前工作目录os.chdir ('F:\eclipse\workspace\learn\extend')
#在F:\eclipse\workspace\learn\extend这个目录下有一个之前写好的计算器文件名为calculator.py
#直接导入用import calculator就可以得出结果了。

#如果我导入上节课做的fibonacci螺旋递归代码
#那么一样进入用户交互

>>> import fibonacci3

请输入Fibonacci螺旋层数:8

注意:两个数字不能同时为0!

第一个数字2.6

第二个数字-2.12

2.60 -2.12 0.48 -1.64 -1.16 -2.80 -3.96 -6.76

>>>

那么在编辑器里这样写

print('这是在运行导入的模块')
import fibonacci3

#运行结果:

这是在运行导入的模块
请输入Fibonacci螺旋层数:6
注意:两个数字不能同时为0!
第一个数字2.2
第二个数字0.95

2.20 0.95 3.15 4.10 7.25 11.35
print('这是在运行导入的模块')
import calculator3

#运行结果:

这是在运行导入的模块
1.5

那么看看calculator3.py的源代码:

from __future__ import division

def f(x,o,y):

    print({'+' : x+y, '-' : x-y,'*' : x*y, '/' : x/y}.get(o))

f(3,'/',2)

里面已经做了一个运算,所以import的时候直接是输出结果。如果我们把运算去掉也就是剩下这段代码

from __future__ import division

def f(x,o,y):

    print({'+' : x+y, '-' : x-y,'*' : x*y, '/' : x/y}.get(o))

那么我们再次导入这个模块的时候是只剩下函数,需要额外调用。调用方法为(新建一个mol.py文件):

print('这是在运行导入的模块')
import calculator3
calculator3.f(3, '/', 2)

#注意,调用模块函数的方法是 模块名.函数名(参数值)

#运行结果

这是在运行导入的模块
1.5

这里有个问题,如果我的模块里包含了函数赋值计算,如:

from __future__ import division

def f(x,o,y):
    print({'+' : x+y, '-' : x-y,'*' : x*y, '/' : x/y}.get(o))

f(3,'*',2)

那么我再次运行mol.py文件时会出现两个结果:

这是在运行导入的模块
6
1.5
  第一个结果 6 是模块自身的运算结果,第二个1.5是在mol.py里调用模块函数的运算结果。
在实际应用中,有两种情况考虑。
第一是直接执行模块文件的话,里面的运算是需要执行的。
第二是如果是被别人所调用的话,那么模块里的运算程序是不需要执行的
解决方法需要借助一个内置属性,现在在calculator3.py里加一行:

from __future__ import division
def f(x,o,y):
    print({'+' : x+y, '-' : x-y,'*' : x*y, '/' : x/y}.get(o))

print(__name__)
#这个__name__就是内置函数,__name__的值会随着调用的对象不同而变化

 
#如果我们直接运行:

__main__    #这是这个文件的对象名,大概意思是指我们现在调用的是主体程序(按着教程猜的)


#我们在mol.py里调用

print('这是在运行导入的模块')

import calculator3
calculator3.f(3, '/', 2)


#运行结果:

这是在运行导入的模块

calculator3                     #这里__name__的值变成了文件名
1.5

 

因此,可以在calculator3.py里加一个判断,当__name__ ==__main__的时候执行源文件的运算程序,
否则运行模块调用的函数赋值运算。

from __future__ import division
def f(x,o,y):
    print({'+' : x+y, '-' : x-y,'*' : x*y, '/' : x/y}.get(o))
if __name__ == '__main__':
f(3,'*',2)

#那么直接运行calculator3.py的时候会做 f(3,'*',2) 的运算,而在mol.py里运行则不会运算:

print('这是在运行导入的模块')

import calculator3
calculator3.f(3, '/', 2)

#运行结果:
这是在运行导入的模块
1.5

导入模块的时候有顺序限制,一般先从当前目录下查找模块文件,然后再从内置模块中查找
这句怎么理解?
string模块是内置模块,如果我在当前目录新建了一个叫string.py的文件,导入之后如果想使用string内置函数的话,那么程序会先在目录下查找string这个模块,这里新建的string.py会被导入,执行string内置函数的话就会出错。因此要使用string模块的话必须把新建的那个string.py文件删除,同时还得删除刚才导入时生成的一个叫string.pyc的文件。才能正确使用string这个内置模块


Python的模块可以按目录组织为包
创建一个包的步骤是:
1.建立一个名字为包名字的文件夹,
2.在该文件夹下创建一个__init__.py文件,
3.根据需要在该文件夹下存放脚本文件、已编译扩展及子包
4. import pack.m1, pack.m2, pack.m3


示范:新建一个pack.py文件,假如我们要想重复使用calculator3.py里的函数运算,那么可以在calculator3.py所在目录下新建一个文件夹,假如命名为bag,在bag文件夹里新建一个__init__.py文件(必须有),内容可以为空,把需要导入的calculator3.py文件复制进去。那么这个bag文件夹就可以称之为python包。注意,调用模块的py文件不能在包里,如这里新建的pack.py不能放在bag里,否则会报错。
文件结构如图:
QQ图片20140302212938

print('这是在运行导入的python包')
import bag.calculator3      #注意格式,包名字.模块名
bag.calculator3.f(3, '/', 2)        #调用函数时候 包名字.模块名.函数名(参数值)

#运行结果:
这是在运行导入的python包
1.5

小结:
模块导入有import,import as,from import等几种方法。具体区别参考:
http://www.cnblogs.com/allenblogs/archive/2011/11/15/2055149.html 

posted @ 2014-03-02 21:49  小丑戌  阅读(303)  评论(0编辑  收藏  举报