Python基础(十八)
今日主要内容
- 包
一、包
(一)什么是包
- 只要是含有
__init__.py文件的文件夹就是一个包 - 包的本质其实就是一个文件夹,利用包将不同功能的模块组织起来,以此来提高程序的结构性和可维护性
- 包是用来导入的,不是用来执行的,所以它和软件开发规范分文件管理还是有区别的,一个是项目,一个是用来导入的包
- 正因为包是用来导入的,所以运行文件一定要放在包的外面
(二)创建一个包
利用代码创建一个包
import os
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/test.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close() ,l)
- 下述所有内容,均以此图结构为基础

(三)__init__.py文件
在我们导入包的时候,其实本质上导入的就是
__init__.py文件,解释器会自动执行__init__.py文件中的内容# glance/__init__.py
print("这里是glance下的__init__.py文件") # run.py
import glance 运行结果:
这里是glance下的__init__.py文件
(四)包的导入
- 包的导入,须注意两点内容:
- 导入时无论是使用
import还是使用from xxx import xxx导入,点的前面必须是一个包 - 使用
from xxx import xxx导入时,import前可以出现点,import后不能出现点
- 导入时无论是使用
常规导入
- import导入
# policy.py
def policy_func():
print("这是policy文件中的函数") # run.py
import glance.api.policy glance.api.policy.policy_func() 运行结果:
这是policy文件中的函数 # 成功导入
- from import导入
# policy.py
def policy_func():
print("这是policy文件中的函数") # run.py
from glance.api.policy import policy_func policy_func() 运行结果:
这是policy文件中的函数 # 成功导入
包内部之间的导入:
包内部之间的相互引用,只能用绝对导入和相对导入,不能直接导入,比如
policy.py文件需要导入versions.py文件中的函数,如果直接import导入会报找不到该模块的错误- 包内部互相引用的时候不能直接导入
# versions.py
def versions_func():
print("这是versions文件中的函数") # policy.py
import versions # 直接导入versions模块,在外面的run文件中运行,就无法找到versions模块 def policy_func():
versions.versions_func()
print("这是policy文件中的函数") # run.py
from glance.api import policy policy.policy_func() 运行结果:
ModuleNotFoundError: No module named 'versions'
- 原因分析:如果直接在policy文件中运行程序,完全没有问题,因为此时policy文件的模块查找路径中包含versions模块,但是**包是用来导入的,如果在包外的run文件中导入policy模块,此时模块查找路径就变为了run文件所在的路径,所以当policy文件导入versions模块时,路径下并没有versions模块,所以找不到该模块
绝对导入:
# versions.py
def versions_func():
print("这是versions文件中的函数") # policy.py
from glance.api import versions def policy_func():
versions.versions_func()
print("这是policy文件中的函数") # run.py
from glance.api import policy policy.policy_func() 运行结果:
这是versions文件中的函数
这是policy文件中的函数
- 相对导入:
# versions.py
def versions_func():
print("这是versions文件中的函数") # policy.py
from . import versions def policy_func():
versions.versions_func()
print("这是policy文件中的函数") # run.py
from glance.api import policy policy.policy_func() 运行结果:
这是versions文件中的函数
这是policy文件中的函数
- 只要使用了相对导入的模块,只能作为模块使用,不能作为脚本(终端中直接运行的文件成为脚本)使用,说白了就是不能直接运行
# versions.py
def versions_func():
print("这是versions文件中的函数") # policy.py
from . import versions def policy_func():
versions.versions_func()
print("这是policy文件中的函数") 运行结果:
ImportError: cannot import name 'versions'
单独导入包,并使用包内的包或模块
- 单独导入一个包,其本质上导入的只是
__init__.py文件,包中其他的文件并没有被导入
# policy.py
def policy_func():
print("这是policy文件中的函数") # run.py
import glance # 只导入了__init__.py文件 glance.api.policy.policy_func() # 并不能使用 运行结果:
AttributeError: module 'glance' has no attribute 'policy'- 此时就要利用到
__init__.py文件了,__init__.py文件在包中起到了交接管理的作用,可以在__init__.py文件中导入每个子文件,也可以控制其是否能被导入,所以每一个包中必须要有__init__.py文件
# policy.py
def policy_func():
print("这是policy文件中的函数") # glance/__init__.py
from . import api # glance/api/__init__.py
from . import policy # run.py
import glance glance.api.policy.policy_func() 运行结果:
这是policy文件中的函数- 直接调用模块中的方法
# policy.py
def policy_func():
print("这是policy文件中的函数") # glance/__init__.py
from .api import * # glance/api/__init__.py
from .policy import * # run.py
import glance glance.policy_func() 运行结果:
这是policy文件中的函数还可以通过
__all__来控制模块和模块中函数的导入- 控制模块导入
# glance/__init__.py
from .api import * # glance/api/__init__.py
__all__ = ["versions"] # 只能导入versions,其余api下模块都不能被导入 # run.py
import glance glance.policy 运行结果:
AttributeError: module 'glance' has no attribute 'policy'- 控制方法导入
# policy.py
def policy_func():
print("这是policy文件中的func") def policy_foo():
print("这是policy文件中的foo") # glance/__init__.py
from .api import * # glance/api/__init__.py
from .policy import *
__all__ = ["policy_foo"] # 控制只能导入foo函数,其余函数都不能被导入 # run.py
import glance glance.policy_func() 运行结果:
AttributeError: module 'glance' has no attribute 'policy_func'
- 单独导入一个包,其本质上导入的只是
Python基础(十八)的更多相关文章
- Bootstrap <基础十八>面包屑导航(Breadcrumbs)
面包屑导航(Breadcrumbs)是一种基于网站层次信息的显示方式.以博客为例,面包屑导航可以显示发布日期.类别或标签.它们表示当前页面在导航层次结构内的位置. Bootstrap 中的面包屑导航( ...
- python 基础(十) 面向对象
面向对象 一.概念 类(class): 用来描述具有相同属性和方法的对象的集合 对象是类的实例化 类变量:类变量在整个实例化的对象中是共用的.定义在类中 并且是函数体外的 实例变量:只能作用于 当前类 ...
- python基础(八种数据类型)
Python的八种数据类型 八种数据类型分别是: number(数字).string(字符串).Boolean(布尔值).None(空值) list(列表).tuple(元组).dict(字典).se ...
- python基础-第八篇-8.1初识Socket
socket基础 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. so ...
- Python基础(八)装饰器
今天我们来介绍一下可以提升python代码逼格的东西——装饰器.在学习装饰器之前我们先来复习一下函数的几个小点,方便更好的理解装饰器的含义. 一.知识点复习 1, 在函数中f1和f1()有什么不同,f ...
- python基础知识八
当你的程序中出现某些 异常的 状况的时候,异常就发生了.例如,当你想要读某个文件的时候,而那个文件不存在.或者在程序运行的时候,你不小心把它删除了.上述这些情况可以使用异常来处理. 如你的程序中有一些 ...
- python基础(八)-迭代器与生成器
一.迭代器 li=[1,2,3] f=li.__iter__() print(f) print(f.__next__()) print(f.__next__()) print(f.__next__() ...
- Python爬虫(十八)_多线程糗事百科案例
多线程糗事百科案例 案例要求参考上一个糗事百科单进程案例:http://www.cnblogs.com/miqi1992/p/8081929.html Queue(队列对象) Queue是python ...
- Python基础篇(八)
key words:私有变量,类静态变量,生成器,导入Python模块,r查看模块可以使用的函数,查看帮助信息,启动外部程序,集合,堆,时间模块,random模块,shelve模块,文件读取等 > ...
- 小甲鱼Python第十八讲课后习题
笔记: 1.函数与过程:过程(procedure)是简单的,特殊且没有返回值的:函数(Function)有返回值 Python严格来说只有函数没有过程 2.局部变量:在局部生效如在函数中定义的变量 3 ...
随机推荐
- CodeForces 416 B Appleman and Tree DP
Appleman and Tree 题解: 定义dp[u][1] 为以u的子树范围内,u这个点已经和某个黑点相连的方案数. dp[u][0] 为在u的子树范围内, u这个点还未和某个黑点相连的方案数. ...
- CF - 652 E Pursuit For Artifacts 边双联通
题目传送门 题解总结起来其实很简单. 把所有的边双联通分量缩成一个点,然后建立好新边, 然后再从起点搜到终点就好了. 代码: /* code by: zstu wxk time: 2019/02/23 ...
- CF - 1108 E 枚举上界+线段树维护
题目传送门 枚举每个点作为最大值的那个点.然后既然是作为最大值出现的话,那么这个点就是不需要被减去的,因为如果最小值也在这个区间内的话,2者都减去1,对答案没有影响,如果是最小值不出现在这个区间内的话 ...
- Codeforces Round #409 C. Voltage Keepsake(二分+思维)
题目链接:http://codeforces.com/contest/801/problem/C 题意:给出一个充电器每秒钟充p个点,还有n个电器要同时使用a[i]表示第i个电器每秒钟用多少点,b[i ...
- python数据结构——线性表
线性表 线性表可以看作是一种线性结构(可以分为顺序线性结构,离散线性结构) 1. 线性表的种类: 顺序表 元素存储在一大块连续存储的地址中,首元素存入存储区的起始位置,其余元素顺序存放. (元素之间的 ...
- d3.js 制作简单的贪吃蛇
d3.js是一个不错的可视化框架,同时对于操作dom也是十分方便的.今天我们使用d3.js配合es6的类来制作一个童年小游戏–贪吃蛇.话不多说先上图片. 1. js snaker类 class Sna ...
- vim 高级功能
本文章原创首发于公众号:编程三分钟 ,文末二维码. 文本编辑.跳转.删除.复制.替换这些操作用vim确实是快:但是好像仅仅是这样根本不能说服我vim超过鼠标的地方. 花点时间弄熟这些,除了炫技意外,主 ...
- 033 模块4-PyInstaller库的使用
目录 一.PyInstaller库基本介绍 1.1 PyInstaller库概述 1.2 pip的使用 1.3 pip install pyinstaller (cmd命令行) 二.PyInstall ...
- java中多线程执行时,为何调用的是start()方法而不是run()方法
Thead类中start()方法和run()方法的区别 1,start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状 ...
- Unity3D_01_各种寻找GameObject方法
1.GameObject.Find(): 寻找Hierarchy面板中的activie 不为false的游戏对象: 路径如官方事例写法: public class ExampleClass : Mon ...