《python语言基础教程》第十章学习总结:开箱即用


                                                    第一节:模块


一、什么是模块?

模块就是程序,任何Python程序都可作为模块导入。

二、如何创建自定义模块?

第一步:编写程序,示例如下:

#hello.py
print('hello world!')

第二步:告诉解释器去哪里查找这个模块

假设文件存储在了path = '/home/dulingwen/site-packages'中,可使用如下命令:

>>>import sys
>>>sys.path.append('/home/dulingwen/site-packages')

       这告诉解释器,除了查找默认的位置外,还可以到目录/home/dulingwen/site-packages中去查找这个模块。这样做后,就可以导入这个模块了。

注意:当你导入模块时,会发现其所在目录中除源代码文件外,还新建了一个名为 __pycache__的子目录。这个目录包含处理后的文件,Python能够更高效地处理它们。以后再导入这个模块时,如果.py文件未发生变化,Python将导入处理后的文件,否则将重新生成处理后的文件。删除目录 __pycache__ 不会有任何害处,因为必要时会重新创建它。

三、在模块中定义函数和添加测试代码

示例如下:

#hello2.py
#定义函数
def hello():
    print('hello world!')
#测试代码
hello()

此时,导入模块你会发现,自动执行了测试代码hello()函数:

>>>import hello2
hello world!
>>>hello2.hello()
hello world!

四、如何避免上述3的行为:使用变量 __name__

       在主程序中(包括解释器的交互式提示符),变量 __name__ 的值是 '__main__' ,而在导入的模块中,这个变量被设置为该模块的名称,因此可以使用变量 __name__检查模块是作为程序运行还是被导入另一个程序。示例代码如下:

# hello3.py
def hello():
print("Hello, world!")

def test():
hello()

if __name__ == '__main__': 
test()

此时如果导入模块:

>>>import hello3
>>>hello3.hello()
hello world!
>>>hello3.test()
hello world!

五、如何让模块可用

这里共有三种方法:

  • 将模块放在正确的位置

将模块放在正确的位置很容易,只需找出Python解释器到哪里去查找模块,再将文件放在这个地方即可。使用下列代码可以查看:

import sys,pprint
pprint.pprint(sys.path)

输出结果如下:

['/data/ananconda3/envs/tensorflow/lib/python36.zip',
 '/data/ananconda3/envs/tensorflow/lib/python3.6',
 '/data/ananconda3/envs/tensorflow/lib/python3.6/lib-dynload',
 '/data/ananconda3/envs/tensorflow/lib/python3.6/site-packages',
 '/data/tensorflow/models/research',
 '/data/tensorflow/models/research/slim',]

(提示:如果要打印的数据结构太大,一行容纳不下,可使用模块 pprint 中的函数 pprint (而不是普通 print 语句)。 pprint 是个卓越的打印函数,能够更妥善地打印输出。)

只要模块位于类似于site-packages这样的地方,所有的程序就都能够导入它。

  • 告诉解释器到哪里去查找

       将模块放在正确的位置可能不是合适的解决方案,原因很多,比如:不希望Python解释器的目录中充斥着你编写的模块;没有必要的权限,无法将文件保存到Python解释器的目录中;想将模块放在其他地方。

       方法一:使用sys.path.append()

       方法二:标准方法:将模块所在的目录包含在环境变量 PYTHONPATH 中,环境变量 PYTHONPATH 的内容随操作系统而异(但它基本上类似于sys.path,也是一个目录列表)。示例如下,可以将~/python 附加到环境变量 PYTHONPATH 末尾:

export PYTHONPATH=$PYTHONPATH:~/python

如果要对所有启动的shell都执行这个命令,可将其添加到主目录中的.bashrc文件中。也可以采用下列方式设置环境变量。

     设置永久环境变量并立即生效:

    系统环境变量可存储在以下文件中:

  • /etc/profile

  • /etc/profile.d(它是文件夹)

  • /etc/bash.bashrc

    首先设置永久环境变量实例(以/etc/profile为例):

gedit /etc/profile
#或者
vim /etc/profile

在文件末尾处添加如下,保存并退出:

export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages/gdal.py

      方法三:使用路径配置文件,这些文件的扩展名为.pth,位于一些特殊目录中,包含要添加到 sys.path 中的目录。示例如下:

#from /data/ananconda3/envs/tensorflow/lib/python3.6/site-packages
touch tf_odi.pth
gedit tf_odi.pth

#在tf_odi.pth文件中手动添加如下路經
home/dulingwen/tensorflow/models/research

六、什么是“包”

        为组织模块,可将其编组为包(package)。包其实就是另一种模块,但有趣的是它们可包含其他模块。模块存储在扩展名为.py的文件中,而包则是一个目录。要被Python视为包,目录必须包含文件__init__.py。要将模块加入包中,只需将模块文件放在包目录中即可。你还可以在包中嵌套其他包。一种简单的包布局如下

文件/目录描述

~/python/

~/python/drawing/

~/python/drawing/__init__.py

~/python/drawing/colors.py 

~/python/drawing/shapes.py

PYTHONPATH 中的目录

包目录(包 drawing )

包代码(模块 drawing )

模块 colors

模块 shapes

 


                                                第二节:探索模块


一、模块包含什么?

1.使用 dir

       要查明模块包含哪些东西,可使用函数 dir ,它列出对象的所有属性(对于模块,它列出所有的函数、类、变量等),如果将 dir(module) 的结果打印出来,将是一个很长的名称列表(请试试看)。在这些名称中,有几个以下划线打头。根据约定,这意味着它们并非供外部使用。有鉴于此,我们使用一个简单的列表推导将这些名称过滤掉。

>>> import copy

>>> dir(copy)
['Error', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_copy_dispatch', '_copy_immutable', '_deepcopy_atomic', '_deepcopy_dict', '_deepcopy_dispatch', '_deepcopy_list', '_deepcopy_method', '_deepcopy_tuple', '_keep_alive', '_reconstruct', 'copy', 'deepcopy', 'dispatch_table', 'error']

>>> [n for n in dir(copy) if not n.startswith('_')]
['Error', 'copy', 'deepcopy', 'dispatch_table', 'error']
#结果包含 dir(copy) 返回的不以下划线打头的名称,这比完整清单要好懂些。

2.变量 “__all__”

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

(1)变量 “__all__”怎么来的?

   它是在模块 copy 中像下面这样设置的(这些代码是直接从copy.py复制而来的):

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

(2)为什么提供它?

  旨在定义模块的公有接口。具体地说,它告诉解释器从这个模块导入所有的名称意味着什么。因此,如果你使用如下代码:

  from copy import *

将只能得到变量 __all__ 中列出的4个函数。要导入 PyStringMap ,必须显式地:导入 copy 并使用copy.PyStringMap;或者使用 from copy import PyStringMap 。编写模块时,像这样设置 __all__ 也很有用。因为模块可能包含大量其他程序不需要的变量、
函数和类,比较周全的做法是将它们过滤掉。如果不设置 __all__ ,则会在以 import * 方式导入时,导入所有不以下划线打头的全局名称。

3.使用 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 只接受一个参数 x,且执行的是浅复制。在帮助信息中,还提到了模块的 __doc__ 字符串。首先介绍一下文档字符串:文档字符串就是在函数开头编写的字符串,用于对函数进行说明。而函数的属性 __doc__ 可能包含这个字符串。

>>> print(copy.copy.__doc__)
Shallow copy operation on arbitrary Python objects.

    See the module's __doc__ string for more info.

显然这种方法不如使用help看到的信息更多。

4.文档

文档是有关模块信息的自然来源。

>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).

        然而,并非每个模块和函数都有详尽的文档字符串(虽然应该如此),且有时需要有关工作原理的更详尽描述,因此提供以下几个参考文件:

           Python库参考手册

           Python 语言参考

5.使用源代码

        多数情况下前面讨论的探索技巧都够用了。但要真正理解Python语言,可能需要了解一些不阅读源代码就无法了解的事情。事实上,要学习Python,阅读源代码是除动手编写代码外的最佳方式。那么源代码在哪里呢?这里提供一个查找源代码的快捷的方式:查看模块的特性“ __file__ ”。示例如下:

>>> print(copy.__file__)
/data/ananconda3/lib/python3.7/copy.py

找到了!你可在代码编辑器(如IDLE)中打开文件copy.py,并开始研究其工作原理。如果列出的文件名以.pyc结尾,可打开以.py结尾的相应文件。

警告:在文本编辑器中打开标准库文件时,存在不小心修改它的风险。这可能会破坏文件。因此关闭文件时,千万不要保存你可能对其所做的修改。

请注意,有些模块的源代码你完全无法读懂。它们可能是解释器的组成部分(如模块 sys ),还可能是使用C语言编写的(如果模块是使用C语言编写的,应该能够获取其C语言源代码。有关如何使用C语言扩展Python的详细信息,请参阅第17章)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值