搞懂Python包之后,感觉学Python轻松多了1.前言2.Python包3.包初始化4.Importing * From a Package5.子包

原标题:搞懂Python包之后 , 感觉学Python轻松多了
来源:麦叔编程
作者:麦叔
1.前言学习方法不对 , 事倍功半!学习方法对了 , 事半功倍 。
学编程 , 要先扎实的学好基础语法和结构 , 剩下的就是不断的实战应用 , 同时按需加强相关知识 。
Python的包就是这里说的基础语法结构之一 。
把手放在胸口上 , 问问自己 , 你对Python包的了解有多少?然后认真看完本文 。 你的今天一定是有进步的 。
包是基于模块的 , 是对模块的组织 , 建议和另一篇模块文章一起看 , 融会贯通起来 。 模块文章链接见文末往期推荐第1篇 。
2.Python包假设你已经开发了一个包含许多模块的非常大的应用程序 。 随着模块数量的增长 , 如果将它们都放到一个位置 , 则很难跟踪所有模块 。 如果它们有相似的名称或功能 , 情况会更糟 。 你可能希望把他们放在不同的文件夹中 , 这就是Python中的包 。
包(package)允许使用点表示法对模块名称空间进行分层结构 。 就像模块可以避免全局变量名之间的冲突一样 , 包也可以避免模块名之间的冲突 。
创建包非常简单 , 因为它利用了操作系统固有的分层文件结构 。 参考下面的目录结构:
pkg
├──mod1.py
└──mod2.py
这里有一个名为pkg的目录 , 其中包含两个模块 , mod1.py和mod2.py 。 模块的内容有:
mod1.py
deffoo():
print('[mod1]foo()')
classFoo:
pass
mod2.py
defbar():
print('[mod2]bar()')
classBar:
pass
根据这个结构 , 如果pkg目录位于一个可以找到它的位置(在sys.path中包含的一个目录中) , 你可以用点符号引用这两个模块(pkg.mod1,pkg.mod2) , 然后用你已经熟悉的语法导入它们:
import<module_name>[,<module_name>...]
>>>importpkg.mod1,pkg.mod2
>>>pkg.mod1.foo()
[mod1]foo()
>>>x=pkg.mod2.Bar()
>>>x
<pkg.mod2.Barobjectat0x033F7290>
from<module_name>import<name(s)>
>>>frompkg.mod1importfoo
>>>foo()
[mod1]foo()
from<module_name>import<name>as<alt_name>
>>>frompkg.mod2importBarasQux
>>>x=Qux()
>>>x
<pkg.mod2.Barobjectat0x036DFFD0>
你也可以用这些语句来导入模块:
from<package_name>import<modules_name>[,<module_name>...]
from<package_name>import<module_name>as<alt_name>
>>>frompkgimportmod1
>>>mod1.foo()
[mod1]foo()
>>>frompkgimportmod2asquux
>>>quux.bar()
[mod2]bar()
从技术上讲 , 你也可以直接导入这个包:
>>>importpkg
>>>pkg
<module'pkg'(namespace)>
但这没什么用 。 尽管严格地说 , 这是一个语法正确的Python语句 , 但它并没有把pkg中的任何模块放到本地命名空间中:
>>>pkg.mod1
Traceback(mostrecentcalllast):
File"<pyshell#34>",line1,in<module>
pkg.mod1
AttributeError:module'pkg'hasnoattribute'mod1'
>>>pkg.mod1.foo()
Traceback(mostrecentcalllast):
File"<pyshell#35>",line1,in<module>
pkg.mod1.foo()
AttributeError:module'pkg'hasnoattribute'mod1'
>>>pkg.mod2.Bar()
Traceback(mostrecentcalllast):
File"<pyshell#36>",line1,in<module>
pkg.mod2.Bar()
AttributeError:module'pkg'hasnoattribute'mod2'
要实际导入模块或其内容 , 需要使用上面展示的import例子 。
3.包初始化如果一个名为__init__.py的文件存在于包目录中 , 它会在导入包或包中的模块时被调用 。 这可以用于执行包初始化代码 , 比如包级数据的初始化 。
例如以下__init__.py文件:
__init__.py
print(f'Invoking__init__.pyfor{__name__}')
A=['quux','corge','grault']
让我们把上面例子中的这个文件添加到pkg目录中:
pkg
├──__init__.py
├──mod1.py
└──mod2.py
现在 , 当包被导入时 , A就会被初始化:
>>>importpkg
Invoking__init__.pyforpkg
>>>pkg.A
['quux','corge','grault']
包中的模块可以访问包里的全局变量:
mod1.py
deffoo():
frompkgimportA
print('[mod1]foo()/A=',A)
classFoo:
pass
>>>frompkgimportmod1
Invoking__init__.pyforpkg
>>>mod1.foo()
[mod1]foo()/A=['quux','corge','grault']
__init__.py也可以用来实现从包中自动导入模块 。 例如 , 前面你看到importpkg语句只将名称pkg放在调用者的局部符号表中 , 而不导入任何模块 。 但是如果pkg目录中的__init__.py包含以下内容:
__init__.py
print(f'Invoking__init__.pyfor{__name__}')