快乐学习
前程无忧、中华英才非你莫属!

Day10-人生苦短我学python

第10章 | 充电时刻

本章主要介绍模块及其工作机制

模块

>>> import math
>>> math.sin(0)
0.0

模块是程序

一个简单的模块

- #hello.py

- print ("Hello,World!")
- >>> import hello
- Traceback (most recent call last):
-   File "<pyshell#56>", line 1, in <module>
-     import hello
- ImportError: No module named hello
- >>> import sys
- >>> sys.path.append('d:/python')

#这里所做的只是告诉解释器,除了从默认的目录寻找外,还需要从d:/python目录下寻找模块。或者将刚才的hello.py放到python的安装目录也是可以的。

- >>> import hello
- Hello,World!

注意:hello.pyc文件出现,该文件是平台无关的,经过处理的,已经转换成Python能够有效处理的文件。如果稍后导入同一模块,python会导入.pyc文件,而不是.py文件,除非.py文件已改变。删除.pyc文件不会损害程序,只要等效的.py文件存在即可。

>>> import hello

再次导入就什么都没有,这是因为导入模块并不意味着在导入时执行某些操作,比如说打印文件。它们主要用于定义,比如变量、函数和类等。此外,因为只需要定义这些东西一次,导入模块多次和导入一次的效果是一样的。只导入一次!如果坚持要导入的话,可以用reload(hello)

- >>> reload(hello)
- Hello,World!
- <module 'hello' from 'd:/python\hello.pyc'>

 

模块用于定义:

在模块中定义函数:

- #hello2.py

- def hello():
-     print ("Hello,World!")
- >>> import hello2

#可以用下面方式来访问函数

- >>> hello2.hello()
- Hello,World!

为什么不在主程序中写好一起呢?主要是为了代码的重用,如果把代码放到模块中的话,就可以多个模块使用它了。因为,请记住:如果让代码可重用,请将它模块化。

在模块中增加测试代码

- #hello3.py

- def hello():
-     print ("Hello,World!")
-

- #A Test

- hello()

#这看起来是合理的-如果将其作为普通程序运行,会发现它能够正常工作,但如果将其作为模块导入,然后再其他程序中使用hello函数,测试代码就会被执行.

- >>> import hello3
- Hello,World!
- >>> hello3.hello()
- Hello,World!

这可能不是我们想要的。避免这种情况的关键在于:告知模块本身是作为程序运行呢? 还是导入到其他程序,为了实现这一点,需要使用__name__变量:

- >>> __name__
- '__main__'

- >>> hello3.__name__
- 'hello3'

在主程序(包括解释器的交互式提示符在内)中,变量__name__的值是'__main__',因此为了让测试模块更加好用,可以加入if条件进行判断,是主程序在掉的话,则运行测试模块,如果只是作为模块导入的话,则不运行测试模块,即整个程序.

- #hello4.py

- def hello():
-     print ("Hello,World!")
-

- #A Test

- def test():
-     hello()
-

- if __name__=='__main__':
-     test()

输出结果:

- >>> import hello4
- >>> hello4.hello()
- Hello,World!

这样更加灵活,即使将其作为模块导入其他程序中,依然可以对其进行测试。

- >>> hello4.test()
- Hello,World!

NOTE: 如果需要编写更完善的测试代码,将其放置在单独的程序中,效果会更好。

 

让你的模块有用:

一是:将模块放置在正确的位置.

二是:告诉解释器去那里寻找需要的模块

将模块放置在正确的位置

目录列表可以再sys.path里面找到

- >>> import sys,pprint
- >>> pprint.pprint(sys.path)
- ['',
-  'C:\\Python27\\Lib\\idlelib',
-  'C:\\WINDOWS\\system32\\python27.zip',
-  'C:\\Python27\\DLLs',
-  'C:\\Python27\\lib',
-  'C:\\Python27\\lib\\plat-win',
-  'C:\\Python27\\lib\\lib-tk',
-  'C:\\Python27',
-  'C:\\Python27\\lib\\site-packages',
-  'C:\\Python27\\lib\\site-packages\\wx-2.8-msw-unicode']

尽管这些目录都可以使用,但site-packages目录是最佳选择,专门用来放置模块的,将之前的hello4.py放在这里

- >>> import hello
- >>> hello.test()
- Hello,World!

NOTE:如果数据结构过大,不能一行打印完,可用pprint函数。pprint是个非常的打印函数,可以提供更加智能的打印输出.

 

告诉编译器去那里找

1. 如果不希望将自己的模块填满Python解释器的目录.

2. 如果没有在python解释器目录存放文件的权限

3. 如果想将模块放在其他地方。

那么就需要告诉解释器去哪里找。

一种是编辑sys.path,但这只是临时生效,所以不常用

>>> sys.path.append('d:/python')

一种是在PYTHONPATH中包含模块的目录.

- Win:
- PYTHONPATH=C:\Python27;.;
- Lin:
- 设置.bashrc文件
- export PYTHONPATH=$PYTHONPATH:~/python

 

模块所在的目录。为了让Python将其作为包对待,必须包含一个__init__.py的模块。如果将它作为普通模块导入的话,文件的内容就是包的内容。比如说有个constants的包,文件constants/__init__.py包括语句PI=3.14,那么可以这样使用.

- >>> import constants
- >>> constants.PI
- 3.14

- >>> dir(constants)
- ['PI', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

假如drawing包下,包括color,shape,__init__模块,且都加到了PYTHONPATH里面了。

下面三种方式都可以

- >>> import drawing
- >>> import drawing.color
- >>> from drawing import shape

 

探究模块:

模块中有什么:

1.使用dir

#她会将对象的所有特性列出,包括模块的所有函数,类,变量

- >>> import copy
- >>> 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']

#其中很多是__开始的,用列表推导式filter过滤一下,就成了:

>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'PyStringMap', 'copy', 'deepcopy', 'dispatch_table', 'error', 'name', 't', 'weakref']
------

2. __all__变量

#这个变量包含一个列表,可以看看

>>> copy.__all__
['Error', 'copy', 'deepcopy']

如何设置的呢? 它是在copy模块内部被设置的

__all__ = ['Error','copy','deepcopy']

那么它为什么在那呢? 它定义了模块的公有接口(public interface)。更准确地说,它告诉解释器:从模块导入所有名字代表什么含义。如果使用如下代码:

>>> from copy import *

那么只能使用__all__变量中的3个函数。如果要导入PyStringMap的话,就得copy.PyStringMap,或者from copy import PyStringMap.

NOTE: 在编写模块的时候,设置__all__是非常有用的.

如果设置的话,模块中一大陀不需要的变量,函数和类,下化线,__all__都会将他们过滤除去。

如果没设置的话,import *默认将输出所有模块中所有非_开头的全局名称.

<span style="font-family: SimHei; font-size: 18px;"--<----

用help获取帮助:

- >>> help(copy)
- Help on module copy:
-

-

- NAME
-     copy - Generic (shallow and deep) copying operations.
-

-

- FILE
-     c:\python27\lib\copy.py
-

-

- DESCRIPTION
-     Interface summary:
-

-             import copy
-

-             x = copy.copy(y)        # make a shallow copy of y

-             x = copy.deepcopy(y)    # make a deep copy of y

- ...
- >>> 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.copy.__doc__  #copy模块的copy函数的文档

- "Shallow copy operation on arbitrary Python objects.\n\n    See the module's __doc__ string for more info.\n    "

 

文档:

如果要查看有关range的描述

- >>> range.__doc__
- 'range(stop) -> list of integers\nrange(start, stop[, step]) -> list of integers\n\nReturn a list containing an arithmetic progression of integers.\nrange(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.\nWhen step is given, it specifies the increment (or decrement).\nFor example, range(4) returns [0, 1, 2, 3].  The end point is omitted!\nThese are exactly the valid indices for a list of 4 elements.'

如果想说明透彻描述这些模块,函数如何工作的,就得学会库参考。学习Python编程,最重要的莫过于Python库参考.https://www.python.org/doc/lib

可以在线查阅,也供下载

所有文档可以再此网站找到

https://www.python.org/doc/

<span style="font-family: SimHei; font-size: 18px;"--<----

使用源代码:

学些Python,最好的方法,首先是自己学代码,其次是学习源代码。

如何找首先在sys.path里面找,其次是检查__file__属性

>>> copy.__file__
'C:\\Python27\\lib\\copy.pyc'

NOTE: 

1.如果是.pyc结尾的,找对应的.py就可以了。

2.有些模块并没有源代码,比如用C语言写的sys模块,她就嵌套在解释器中

WARN: 用编辑器打开源代码文件,可能修改文件,注意不要SAVE,以免修改文件.

<span style="font-family: SimHei; font-size: 18px;"--<----

标准库: 一些最爱

sys: 让你能够访问与Python解释器紧密联系的变量和函数

sys.argv: 传递到Python解释器的参数,包括脚本名称

sys.exit: 退出当前程序,如果在try/finally中调用,finally子句仍然会执行,在Linux中,可以提供一个整数作为参数,标志程序运行正常与否,如exit 0,成功运行.

sys.modules: 将模块名映射到实际存在的模块上,它只应用于目前导入的模块.

sys.path: 目录字符串列表,import模块,Python解释器会从这些目录查找模块

sys.platform: 运行Python平台的名称

sys.stdin,sys.stdout,sys.stderr模块变量是类文件流对象.标准输入,标准输出,标准错误

- #Filename: reverse.py

- import sys
- args = sys.argv[1:]
- args.reverse()
- print ' '.join(args)
- D:\Work\Python>python reverse.py A B C
- C B A

 

os:

提供了访问多个操作系统服务的功能

打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Day10-人生苦短我学python

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!