python contains类似函数_免费视频教程!零基础学Python系列(27) 模块和包1

点击  跟哥一起学Python 关注我们 d57fb6219eedf331ecd7a6de762f06ac.png实例源码

本节视频涉及到的实例源码,可以在百度网盘中下载。在公众号对话框回复关键字“网盘地址”,获取网盘链接和提取码。

课件

01

组织你的代码

通常,我们的程序不会只有一个函数,如果功能需求稍微复杂的程序,也不会都写在一个.py文件里面。这就涉及到一个问题,我们该如何组织这些.py文件呢? 正如我们日常工作中将我们的文档通过文件夹分类一样,我们也通过.py文件以及文件夹的方式进行分类组织。一个大的项目可能有数百个.py文件,这种分类手段是有必要的,而且是必需的。

32dd918d29cc45c3302c98fded84620e.png

我们将.py文件称作python的模块(module),而将这种文件夹(带__init__.py),称之为python的包(package)。 我们利用模块和包,可以更好地组织我们项目的代码。同时,它们也提供了类似函数那样的代码复用能力。 我们来看python官方手册提供的一个典型案例,下面是一个关于“声音处理”的包目录层次结构: sound/                          Top-level package       __init__.py               Initialize the sound package       formats/                  Subpackage for file formatconversions               __init__.py               wavread.py               wavwrite.py               aiffread.py               aiffwrite.py               auread.py               auwrite.py               ...       effects/                  Subpackage for sound effects               __init__.py               echo.py               surround.py               reverse.py               ...       filters/                  Subpackage for filters               __init__.py               equalizer.py               vocoder.py               karaoke.py               ... “声音处理”包含了很多功能,比如对各种声音格式的支持、音效增强、过滤器等等。我们将这些功能进行分层拆分,分别放在不同的.py和package中实现。 这里的sound是一个顶层的package,而formats、filters、effects是它的子package,package支持这样的层层嵌套,和文件夹目录一样。需要注意的是,只有包含了__init__.py的目录才会被认为是一个package,否则它就是一个普通的文件夹。__init__.py可以为空,后面我们会详细介绍它的写法。 这里面的所有.py文件都是模块。模块里面的内容没有要求,可以包含变量、函数、类,也可以为空。   Python解释器本身提供了庞大的标准库,其本质就是模块或者包。我们使用比较多的re、datetime、copy、array、enum、os、sys、io等等都是标准库。 你可以通过查询官方的标准库参考手册: https://docs.python.org/zh-cn/3/library/index.html 后面我们也会重点介绍一些常用的标准库。

02

模块的三种导入方式

模块和包,是可以被复用的。比如上面的sound包,我们可以在其它的python程序中导入它,并调用它里面的函数、变量或者类。 这一过程,通过Import机制来实现,如下是最简单的方式:
#  author: Tiger,   关注公众号“跟哥一起学python”,ID:tiger-python# file: ./10/10_1.py# 模块import keywordprint(keyword.kwlist)

我们通过import导入了一个模块keyword,并接下来获取了它的一个变量kwlist打印出来。

Import语句需要写在使用它的代码之前,而通常我们是建议所有的import语句都写在文件的开头。

我们看看keyword.py是什么样的?它非常简单:

# LIB/keyword.py __all__ =["iskeyword", "kwlist"] kwlist = [    'False',    'None',    'True',    'and',    'as',    'assert',    'async',    'await',    'break',    'class',    'continue',    'def',    'del',    'elif',    'else',    'except',    'finally',    'for',    'from',    'global',    'if',    'import',    'in',    'is',    'lambda',    'nonlocal',    'not',    'or',    'pass',    'raise',    'return',    'try',    'while',    'with',    'yield'] iskeyword =frozenset(kwlist).__contains__
第一行,给一个叫__all__的变量进行了赋值。 这个变量有特殊含义,它是给python解释器看的,它表示在import该模块时需要导入的符号列表。 第二行,定义了一个变量kwlist,是一个列表,它里面存了python的所有保留字。 第三行,定义iskeyword是frozenset的一个内建函数__contains__,它判断一个字符串是不是kwlist里面的保留字。   我们还可以通过 from xxx importxxx 的方式导入:
from keyword importkwlistprint(kwlist)
这种导入比前面的要精确,范围更小。这种导入方式适合你明确知道你需要的功能的时候,比如这个例子中,我明确知道我只需要打印kwlist,所以可以指定只导入kwlist。 这种方式在使用时会显得更加简洁,我们只需要使用kwlist即可,而不用像上面那样写keyword.kwlist。 另一个好处是,第一种方式会把这个模块的所有符号一股脑的全部导入进来,而第二种方式则更加精确。当我们需要使用同一个模块中的多个函数或者变量时,我们可以采用第一种方式,因为采用第二种方式的话我们会写多次from xxx import xxx。   无论上面哪种方式,它们都存在命名冲突的风险。比如我们自己的程序中可能已经存在一个变量叫做keyword或者kwlist了。这时候我们需要为我们导入的模块或者函数起一个别名,如下:
import keyword askwmodulefrom keyword importkwlist as kwallprint(kwmodule.kwlist)print(kwall)

我们通过as xxx来起别名,如上kwmodule就是keyword模块的别名,而kwall就是变量kwlist的别名。在下面的使用中,我们就只能使用这个别名。这就解决了命名重复的问题。

第二种导入方式也可以导入模块中所有的符号(变量、函数、类等),需要使用*通配符来表示。它和第一种方式的全部导入,是有区别的。第一种方式导入的符号是keyword,模块中的所有符号都包含在keyword里面,所有调用方式都必须是keyword.xxx的方式。而采用*号通配符,则是将模块中的符号全部导入进来,可以直接调用。 我们可以通过dir(obj)内建函数,打印出某个对象的符号表,如果不带参数,则打印当前模块的符号表。
import keywordprint(dir())print(dir(keyword))

输出为:

['__annotations__', '__builtins__', '__cached__','__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__','keyword']

['__all__', '__builtins__', '__cached__', '__doc__','__file__', '__loader__', '__name__', '__package__', '__spec__', 'iskeyword','kwlist']

前面那些__XXX__的大家先不用关注,他们是python对象自带的符号。我们看到,这种import方式,它只导入了keyword。而keyword里面包含了iskeyword和kwlist。

from keyword import *print(dir())

输出为:

['__annotations__', '__builtins__', '__cached__', '__doc__','__file__', '__loader__', '__name__', '__package__', '__spec__', 'iskeyword','kwlist']

这种方式是直接把模块中的符号导入进来了,平铺在当前符号表中。 *号通配符的方式,通常不被推荐使用。一个重要的原因是,如果模块中的符号很多的时候,你很难保证不出现重名的情况,重名导致的覆盖会让你的程序变得很难看懂,而且容易出错。另外,我们的程序中通常会导入多个外部模块,要保证这些模块中的符号相互之间不命名冲突,几乎是不可能的。

下一节我们继续讲模块和包。

-end-


c1d6cc900c5c8d6dac9700d16806e4cb.png

有问题请评论留言,欢迎交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值