充电时刻——模块
python的标准安装包含一组模块,称为标准库。
模块
>>> import math
>>> math.sin(0)
0.0
模块是程序
不论什么python程序都能够作为模块导入。
$ cat hello.py
#!/usr/bin/python
print "Hello,signjing!"
$ ./hello.py
Hello,signjing!
如果将python程序保存在/home/ggz2/magiccube/mysh/pys文件夹中,运行以下的代码:
>>> import sys
>>> sys.path.append('/home/ggz2/magiccube/mysh/pys')
这里所做的仅仅是告诉解释器:除了从默认的文件夹中寻找之外,还须要从文件夹/home/ggz2/magiccube/mysh/pys中寻找模块。
完毕这个步骤后,就能导入自己的模块了:
>>> import hello
Hello,signjing!
注意:在导入模块的时候。可能会看到有新文件出现,本例中是/home/ggz2/magiccube/mysh/pys/hello.pyc。这个以.pyc为扩展名的文件是(平台无关的)经过处理(编译)的,已经转换成python可以更加有效地处理的文件。假设稍后导入同一个模块,python会导入.pyc文件而不是.py文件。除非.py文件已经改变——在这样的情况下,会生成新的.pyc文件。
删除.pyc文件不会损害程序(仅仅要等效的.py文件存在就可以)——必要的时候会创建新的.pyc文件。
如你所见。在导入模块的时候。当中的代码就被运行了。只是再次导入该模块。就不会发生什么了。
>>> import hello
>>>
由于导入模块并不意味着在导入时运行某些操作。
它们主要用于定义。
此外,由于仅仅须要定义这些东西一次,导入模块多次和导入一次的效果是一样的。
模块用于定义
模块在第一次导入程序中时被运行。
这看起来有点用——但并不算非常实用。真正的用处在于它们(像类一样)能够保持自己的作用域。这就意味着定义的全部类和函数以及赋值后的变量都成为了模块的特性。
在模块中定义函数
$ cat hello2.py
#!/usr/bin/python
def hello():
print "morning,signjing"
>>> import hello2
>>> hello2.hello()
morning,signjing
能够通过相同的方法来使用不论什么在模块的全局作用域中定义的名称。
为了让代码可重用,请将它模块化!
在模块中添加測试代码
模块用来定义函数、类和其它一些内容。但有些时候(其实是常常)。在模块中加入一些检查模块本身是否正常工作的測试代码是非常实用的。
$ cat hello3.py
#!/usr/bin/python
def hello():
print "Hello!"
# a test
hello()
>>> import hello3
Hello!
>>> hello3.hello()
Hello!
避免这样的情况的关键在于:“告知”模块本身是作为程序执行还是导入到其它程序。为了实现这一点。须要使用__name__(双下划线)变量:
>>> __name__
'__main__'
>>> hello3.__name__
'hello3'
可见。在主程序(包含解释器的交互式提示符在内)中。变量__name__的值是’__main__’。而在导入的模块中。这个值被设定为模块的名字。因此。为了让模块的測试代码更加好用,能够将其放置在if语句中:
$ cat hello4.py
#!/usr/bin/python
def hello():
print "hello"
def test():
hello()
if __name__=='__main__':test()
>>> import hello4
>>>
>>> hello4.hello()
hello
让你的模块可用
将模块放置在正确位置
将你的模块放置在正确位置(或者某个正确位置)是非常easy的。仅仅须要找出python解释器从哪里查找模块。然后将自己的文件放置在那里就可以。
linux系统:
>>> import sys,pprint
>>> pprint.pprint(sys.path)
['',
'/usr/lib64/python26.zip',
'/usr/lib64/python2.6',
'/usr/lib64/python2.6/plat-linux2',
'/usr/lib64/python2.6/lib-tk',
'/usr/lib64/python2.6/lib-old',
'/usr/lib64/python2.6/lib-dynload',
'/usr/lib64/python2.6/site-packages',
'/usr/lib64/python2.6/site-packages/gtk-2.0',
'/usr/lib/python2.6/site-packages']
windows系统:
>>> import sys,pprint
>>> pprint.pprint(sys.path)
['',
'D:\\software(x86)\\Python27\\Lib\\idlelib',
'C:\\Windows\\system32\\python27.zip',
'D:\\software(x86)\\Python27\\DLLs',
'D:\\software(x86)\\Python27\\lib',
'D:\\software(x86)\\Python27\\lib\\plat-win',
'D:\\software(x86)\\Python27\\lib\\lib-tk',
'D:\\software(x86)\\Python27',
'D:\\software(x86)\\Python27\\lib\\site-packages']
每一个字符串都提供了一个放置模块的文件夹。解释器能够从这些文件夹中找到所需的模块。虽然这些文件夹都能够使用。但site-packages文件夹是最佳选择,由于它就是用来做这些事情的。
在windows操作系统中的D:\\software(x86)\\Python27\\lib\\site-packages下创建文件another_hello.py:
def hello():
print "hello,Win7"
>>> import another_hello
>>> another_hello.hello()
hello,Win7
可见。仅仅要将模块放入类似site-packages这种文件夹中,全部程序就都能将其导入了。
告诉编译器去哪里找
“将模块放置在正确的位置”这个解决方式在下面几种情况下可能并不适用:
1)不希望将自己的模块填满python解释器的文件夹;
2)没有python解释器文件夹中存储文件的权限。
3)想将模块放在其它地方
既然如此,那就告诉解释器去哪里找。之前提到了sys.path。但这不是通用的方法。标准的实现方法是在PYTHONPATH环境变量中包括模块所在的文件夹。
PYTHONPATH环境变量的内容会由于使用的操作系统不同而有所差异,但从基本上来说。它与sys.path非常类似——一个文件夹列表。
环境变量并非python解释器的一部分。它们是操作系统的一部分。
提示:不须要使用PYTHONPATH来更改sys.path。
路径配置文件提供了一个实用的捷径。能够让python替你完毕这些工作。路径配置文件是以.pth为扩展名的文件,包含应该加入到sys.path中的文件夹信息。空行和以#开头的行都会被忽略。
以import开头的文件会被运行。对于Windows来说,使用sys.prefix定义的文件夹名;在unix和mac OSX中则使用site-packages文件夹。
命名模块
包括模块代码的文件要和模块名一样——再加上.py扩展名。
在windows系统中,也能够使用.pyw扩展名。
包
为了组织好模块,能够将它们分组为包。包基本上就是另外一类模块。
有趣的地方就是它们都能包括其它模块。
当模块存储在文件里时(扩展名为.py),包就是模块所在的文件夹。为了让python将其作为包对待。它必须包括一个命名为__init__py的文件(模块)。假设将它作为普通模块导入的话,文件的内容就是包的内容。比方有个名为constants的包,文件constants/__init__.py包括语句PI=3.14,那么能够这么做:
import constants
print constants.PI
为了将模块放置在包内。直接把模块放在包文件夹内就可以。
探究模块
怎样独立地探究模块,是极有价值的技能。由于职业生涯中可能会遇到非常多实用的模块。
模块中有什么
探究模块最直接的方式就是在python解释器中研究它们。
第一件事就是导入它。
如果有个叫做copy的标准模块:
>>> import copy
使用dir
查看模块中包括的内容能够使用dir函数,会将对象(以及模块的全部函数、类、变量等)的全部特性列出。
>>> dir(copy)
['Error', 'PyStringMap', '_EmptyClass', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_copy_dispatch', '_copy_immutable', '_copy_inst', '_copy_with_constructor', '_copy_with_copy_method', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_inst', '_deepcopy_list', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', '_test', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']
一些名字下面划线開始——暗示(约定俗成)它们并非为在模块外部使用而准备的。过滤到它们:
>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'PyStringMap', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']
all变量
__all__这个名字包括一个列表,在copy模块内部被设置。
>>> copy.__all__
['Error', 'copy', 'deepcopy']
它定义了模块的公共接口。
更准确地说,它告诉解释器:从模块导入全部名字代表什么含义。
使用例如以下代码from copy import *。则仅仅能使用__all__变量中的函数。要导入PyStringMap的话,就得显式地实现,或者导入copy然后使用copy.PyStringMap,或者使用from copy import PyStringMap。
在编写模块的时候,像设置__all__这种技术还是相当实用的。
由于模块中可能会有一大堆其它程序不须要或不想要的变量、函数和类,__all__会“客气地”将它们过滤了出去。
假设没有设定__all__,用import *语句默认将会输出模块中全部不下面划线开头的全局名称。
用help获取帮助
对于探究工作。交互式解释器是个很强大的工具。而对该语言的精通程度决定了对模块探究的程度。只是还有个标准函数可以为你提供日常所需的信息,这个函数叫做help。
>>> help(copy.copy)
Help on function copy in module copy:
copy(x)
Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
>>>
其实。上面的帮助文档是从copy函数的文档字符串中提取出的:
>>> print copy.copy.__doc__
Shallow copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
>>>
使用help与直接检查文档字符串相比。优点在于获得很多其它信息。
help(copy)会打印出很多其它信息,此处略;
文档
并不是每一个模块或函数都有不错的文档字符串(虽然都应该有)。有些时候可能须要十分透彻地描写叙述这些模块和函数是怎样工作的。
学习python编程最实用的文档莫过于python库參考。它对全部标准库中的模块都有描写叙述。
使用源码
对于希望真正理解python语言的人来说。要了解模块,是不能脱离源码的。
阅读源码其实是学习python最好的方式——除了自己编写代码外。
真正的阅读不是问题,可是问题在于源码那里。假设希望阅读标准模块copy的源码。一种方案是检查sys.path。然后自己找。还有一种是检查模块的__file__属性:
>>> copy.__file__
'D:\\software(x86)\\Python27\\lib\\copy.pyc'
注意:一些模块并不包括不论什么能够阅读的python源码。它们可能已经融入到解释器内了(比方sys模块),或者可能是使用c语言写成的。
python基础教程_学习笔记12:充电时刻——模块的更多相关文章
-
python基础教程_学习笔记14:标准库:一些最爱——re
标准库:一些最爱 re re模块包括对正則表達式的支持,由于以前系统学习过正則表達式,所以基础内容略过,直接看python对于正則表達式的支持. 正則表達式的学习,见<Mastering Reg ...
-
python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/36201499 标准库:一些最爱 集合.堆和双端队 ...
-
python基础教程_学习笔记1:序列-1
序列 数据结构:通过某种方式组织在一起的数据元素的集合,这些数据元素能够是数字或者字符,甚至能够是其它数据结构. python中,最主要的数据结构是序列. 序列中的每一个元素被分配一个序号--即元素的 ...
-
python基础教程_学习笔记10:异常
异常 什么是异常 Python用异常对象来表示异常情况.遇到错误后,会引发异常.假设异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止运行: >>> ...
-
python基础教程_学习笔记9:抽象
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/30745465 抽象 懒惰即美德. 抽象和结构 抽 ...
-
python基础教程_学习笔记11:魔法方法、属性和迭代器
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/31417309 魔法方法.属性和迭代器 在pyth ...
-
python基础教程_学习笔记18:标准库:一些最爱——shelve
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/36029981 标准库:一些最爱 shelve S ...
-
python基础课程_学习笔记15:标准库:有些收藏夹——fileinput
标准库:有些收藏夹 fileinput 重要功能 性能 叙述性说明 input([files[,inplace[,backup]]) 便于遍历多个输入流中的行 filename() 返回当前文件的名称 ...
-
python基础课程_学习笔记26:编程的乐趣
编程的乐趣 编程柔术 当你坐下来,打算如何组织计划要定时,具体程序,然而,无论什么经验.在实现时间的函数的,你会逐渐学会了原来的设计,实用的新知识.我们不应该忽视沿途汲取的教训,相反,它们用于其他设计 ...
随机推荐
-
开始学习c语言
学习c语言的第一篇博客,心里的感觉说不出来,不知道能不能坚持下去,我是一名工作了差不多2年的phper,其实我本来是想学习数据结构和算法的,但是尼玛这年头那些书的例子都不是php,动不动就是c,jav ...
-
spring源码分析之spring jmx
JMX架构定义: https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/overview/architecture.html Archi ...
-
JavaWeb笔记——三大组件之过滤器
过滤器JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的. 当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“ ...
-
SGU 183.Painting the balls
时间限制:0.25s 空间限制:4M 题意: 在n(n<=10000)个球中,给若干个球涂色,每个球涂色的代价为Ci,使得任意连续m(m<=100)个球中有至少两个球被涂了色. Solu ...
-
用JS做图片轮播
脚本之家 首页应用手游攻略教程 ﹤首页 >> 网络编程 >> JavaScript >> 网页特效 >> 图象特效 js 图片轮播(5张图片) 作者:m ...
-
JDBC的使用五大步骤以及查询操作-数据库编程(二)
jdbc的使用步骤 1.加载jdbc的驱动. 2.打开数据库的连接. 3.建立一个会话,然后执行增删改查等基本的操作. 4.对结果进行处理 5.对环境进行清理,比如关闭会话等. 查询操作 首先用Cla ...
-
peewee基本操作
本文将简单的介绍Peewee,一览它的主要特点,主要涉及到: 模型定义 存储数据 检索数据 注意:如果你偏爱稍微高级一点的教程, peewee建立类似twitter应用 是一篇结合Flask框架与pe ...
-
Uva821-Floyd
计算所有页面的平均距离. 用floyd求距离,再求平均 #include <algorithm> #include <cstring> #include <ctype.h ...
-
Shell结合Expect实现自动输入密码
Shell结合Expect自动输入密码示例 #!/bin/bash cd /data/live /usr/bin/expect <<-EOF spawn git clone "s ...
-
【C】C语言中的_exit()与exit()
_exit()和exit()主要区别是一个退出进程会清理I/O缓冲区,一个直接结束进程进入到内核中. 举例说明: #include <stdio.h> /*demo01 程序只输出 hel ...