如何理解Python中包的引入


Posted in Python onMay 29, 2020

Python的from import *和from import *,它们的功能都是将包引入使用,但是它们是怎么执行的以及为什么使用这种语法呢?

从一模块导入全部功能

from import * means意味着“我希望能访问中我有权限访问的全部名称”。例如以下代码something.py:

# something.py
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

在Python解释器中,我们可以执行from something import *,然后看到如下的内容:

>>> from something import *
>>> public_variable
42
>>> _private_variable
...
NameError: name '_private_variable' is not defined
>>> public_function()
"I'm a public function! yay!"
>>> _private_function()
...
NameError: name '_private_function' is not defined
>>> c = PublicClass()
>>> c
<something.publicclass object="" at="" ...="">
>>> c = _WeirdClass()
...
NameError: name '_WeirdClass' is not defined

from something import *从something中导入了除了以_开头名称外的其他所有名称,按照规范,_开始的名称是私有的所以未被导入。

上面没提到__all__是什么。__all__是一个字符串列表,指定了当from import *被使用时,模块(或者如后文会提到的包)中的哪些符号会被导出。如果我们不定义__all__(我们在上面的something.py就没定义),import *默认的导入方式是导入除了下划线(_)开头的所有名称。再说一次,编程惯例上下划线表示一个符号是私有的,不导入是合理的。让我们来看看在something.py中定义我们自己的__all__会发生什么。

# something.py
__all__ = ['_private_variable', 'PublicClass']
# The rest is the same as before
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

现在,我们期望from something import *只会导入_private_variable和PublicClass:

# something.py
__all__ = ['_private_variable', 'PublicClass']
# The rest is the same as before
public_variable = 42
_private_variable = 141
def public_function():
 print("I'm a public function! yay!")
def _private_function():
 print("Ain't nobody accessing me from another module...usually")
class PublicClass(object):
 pass
class _WeirdClass(object):
 pass

包是怎样的呢?

当从一个包中导入全部时,__all__的做法和模块基本一样,不过它处理的是包中的模块(而不是把模块中的名都导入)。所以当我们使用from import *.时__all__说明了所有需要被导入当前命名空间的模块。

不同之处在于,如果你在一个包的__init__.py里面没有声明__all__,from import *语句不会导入任何东西(这个说法也不全对,正确的说法在此)

但是,这有什么不好?

继续读之前,在你的Python解释器中,执行import this,再读一遍Python之禅(在你孩子每晚睡前也要读给他们)。

明确比含糊要好。

from import * 是不明确的。它没告诉我们我们正在导入什么或者我们把什么带入当前命名空间了。更好的做法是显式地导入我们需要的全部名称。这种方式下,读者(非常可能是未来的你自己)就不会困惑于你代码中使用的一个变量/方法/类/其他东西是哪儿来的,这也告诉了我们下一点:

可读性很重要

即使你需要导入很多东西,一个一个显式地导入也更清楚。使用PEP 328:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
 LEFT, DISABLED, NORMAL, RIDGE, END)

你现在就能明确知道你的命名空间里有什么,使用ctrl+f能很快地告诉你它们是哪儿来的。

同时,你还总是要承担模块/包作者更改list内容(加/减东西)的风险。

内容扩展:

基本注意点

  • 模块:一般指一个py文件;包:含有许多py文件的文件夹,含有 或不含有(Python3中允许)__init__文件。
  • 凡是在导入时带点的,点的左边都必须是一个包 (import a.fun1 其中a为py文件)这种导入形式是错误的。
  • 2.from a import fun1 a为一个py文件,fun1为该文件的属性或方法,这种导入形式是可以的。
  • 一般来说 import 后面不能带点,如:(from a import b.c是错误语法)
  • 导入模块时,是将模块的py文件导入进去(执行);导入包时,只会执行包中的__init__文件中的代码,故导入包时一般要导入到最底层,即from dir1.dir2.dir3 import py文件或者类、方法、属性,只有这样才能找到。但是你可以通过先导入一个包,然后在包的文件中的__init__中写相关的import语句(可以绝对,也可以相对),这样也可以通过import 包名 的方式将包中的东西导入进去。

以上就是如何理解Python中包的引入的详细内容,更多关于Python中包的引入详解的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python对列表排序的方法实例分析
May 16 Python
在阿里云服务器上配置CentOS+Nginx+Python+Flask环境
Jun 18 Python
python3读取csv和xlsx文件的实例
Jun 22 Python
在Python 不同级目录之间模块的调用方法
Jan 19 Python
django中上传图片分页三级联动效果的实现代码
Aug 30 Python
python实现静态服务器
Sep 05 Python
numpy.linalg.eig() 计算矩阵特征向量方式
Nov 29 Python
python wav模块获取采样率 采样点声道量化位数(实例代码)
Jan 22 Python
如何通过python实现全排列
Feb 11 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
Jun 09 Python
基于python实现音乐播放器代码实例
Jul 01 Python
Python模拟键盘输入自动登录TGP
Nov 27 Python
浅谈django channels 路由误导
May 28 #Python
Python如何实现FTP功能
May 28 #Python
python基于socket函数实现端口扫描
May 28 #Python
Python中and和or如何使用
May 28 #Python
Python如何安装第三方模块
May 28 #Python
python使用多线程+socket实现端口扫描
May 28 #Python
Python如何实现定时器功能
May 28 #Python
You might like
CodeIgniter扩展核心类实例详解
2016/01/20 PHP
解决Laravel自定义类引入和命名空间的问题
2019/10/15 PHP
PHP数组array类常见操作示例
2020/05/15 PHP
PHP实现简易用户登录系统
2020/07/10 PHP
Laravel统一错误处理为JSON的方法介绍
2020/10/18 PHP
JavaScript 操作键盘的Enter事件(键盘任何事件),兼容多浏览器
2010/10/11 Javascript
javascript 广告后加载,加载完页面再加载广告
2010/11/25 Javascript
Ext JS 4官方文档之三 -- 类体系概述与实践
2012/12/16 Javascript
原生javascript实现图片按钮切换
2015/01/12 Javascript
javascript中使用new与不使用实例化对象的区别
2015/06/22 Javascript
js 获取范围内的随机数实例代码
2016/08/02 Javascript
微信js-sdk地理位置接口用法示例
2016/10/12 Javascript
js实现各种复制到剪贴板的方法(分享)
2016/10/27 Javascript
js制作可以延时消失的菜单
2017/01/13 Javascript
JavaScript中document.referrer的用法详解
2017/07/04 Javascript
WebStorm ES6 语法支持设置&amp;babel使用及自动编译(详解)
2017/09/08 Javascript
提升页面加载速度的插件InstantClick
2017/09/12 Javascript
微信小程序npm引入vant-weapp的踩坑记录
2019/08/01 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
2020/07/26 Javascript
[44:40]Serenity vs Pain 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python文件和目录操作函数小结
2014/07/11 Python
介绍Python中的一些高级编程技巧
2015/04/02 Python
Python使用pickle模块报错EOFError Ran out of input的解决方法
2018/08/16 Python
opencv调整图像亮度对比度的示例代码
2019/09/27 Python
关于pycharm中pip版本10.0无法使用的解决办法
2019/10/10 Python
使用Python函数进行模块化的实现
2019/11/15 Python
Pyqt5自适应布局实例
2019/12/13 Python
Python模块的定义,模块的导入,__name__用法实例分析
2020/01/07 Python
Python 解决火狐浏览器不弹出下载框直接下载的问题
2020/03/09 Python
python读取hdfs上的parquet文件方式
2020/06/06 Python
vscode配置anaconda3的方法步骤
2020/08/08 Python
美国购买体育、音乐会和剧院门票网站:SelectATicket
2019/09/08 全球购物
拉飞逸官网:Lafayette 148 New York
2020/07/15 全球购物
统计每一学生的平均成绩
2014/06/06 面试题
小区消防演习方案
2014/02/21 职场文书
活动新闻稿范文
2015/07/17 职场文书