Importing `*` in Python
来源:互联网 发布:网络推广视频教程 编辑:程序博客网 时间:2024/06/06 22:22
原文链接点击打开链接
This post discusses Python’s from <module> import *
and from <package>import *
, how they behave and why it may be (is!) a bad idea to use them.
Importing *
from a module
from <module> import *
means “I want access to all the names in <module>
that I’m meant to have access to”. So, let’s say we have the followingsomething.py
:
# something.pypublic_variable = 42_private_variable = 141def 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): passclass _WeirdClass(object): pass
In the Python Interpreter, we can execute from something import *
and see the following:
>>> from something import *>>> public_variable42>>> _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
So, from something import *
imports all the names from something
other than the names that start with an _
; because they are conventionally meant to be private.
Ermm, that’s not too bad! Is that __all__?
What’s not mentioned above is what __all__
is. __all__
is a list of strings defining what symbols in a module (or a package as we’ll see later) will be exported when from <module> import *
is used on the module. If we don’t define __all__
(we didn’t in something.py
above), the default behaviour of import *
is to import all names except those beginning with an underscore (_
). Again, since conventionally an underscore is used to say a symbol is private, that all makes sense. Let’s see what happens when we define our own __all__
in something.py
:
# something.py__all__ = ['_private_variable', 'PublicClass']# The rest is the same as beforepublic_variable = 42_private_variable = 141def 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): passclass _WeirdClass(object): pass
Now, we expect from something import *
to only import the_private_variable
and PublicClass
names:
>>> from something import *>>> public_variable...NameError: name 'public_variable' is not defined>>> _private_variable0>>> public_function()...NameError: name 'public_function' is not defined>>> _private_function()...NameError: name '_private_function' is not defined>>> c = PublicClass()>>> c<something.PublicClass object at ...>>>> c = _WeirdClass()...NameError: name '_WeirdClass' is not defined
What about packages?
When importing * from a package, __all__
does approximately the same thing as for modules, except it deals with modules within the package (in contrast to specifying names within the module). So __all__
specifies all modules that shall be loaded and imported into the current namespace when we use from <package> import *
.
However, the difference is, when you omit the declaration of __all__
in a package’s __init__.py
, the statement from <package> import *
will not import anything at all (not entirely true; Read this for the truth).
But, why is this bad?
Before proceeding, in your Python Interpreter, import this
and read The Zen of Python again (read it to your kids every night before they sleep too).
Explicit is better than implicit.
from <module> import *
is not explicit. It isn’t telling us anything about what we’re importing or what names we’re bringing into our namespace. It would be much better to explicitly specify and import everything we need; that way, a reader (most likely your future self) won’t be confused about where a variable/function/class/etc. used in the code comes from, which leads us to:
Readability counts.
Even if a lot of names are required, it’s still much clearer to import them one by one explicitly. Use PEP 328:
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text, LEFT, DISABLED, NORMAL, RIDGE, END)
You now know exactly what you have in your namespace and a quickctrl+f
can tell you where a name has come from.
Also, you are always at risk if/when the module/package author decides to change the contents of the list (add/remove stuff to/from it). Then, either:
- The author has removed a string from
__all__
. If your code was using that name, your code will raise aNameError
and it’ll be harder to find out why. - The author has added [many] new strings to
__all__
. You may not need all/any of the new names and you’re just bloating your namespace with stuff you don’t care about. They may even shadow some other names without you realising.
Of course, sometimes it may be useful or necessary to import *
from modules and/or packages. However, it’s best to make sure you really have to before doing it. In my experience, this construct is usually used as a result of laziness more than anything else.
Discussion on hackernews and reddit.
- Importing `*` in Python
- class Importing Data in Python (Part 1)
- Importing Data in Python (Part 2)
- [Python] Importing Python Modules
- Importing and Exporting in Studio
- Installing/importing a root certificate in Java
- Effective Objective-C: Minimize Importing Headers in Headers
- Importing Python Modules(import and from import, import as)
- 8: Importing A File(Command line Python scripting)
- Away3D in Flex 4 – Phase 3 – Importing MD2 Models
- 解决yum升级的问题“There was a problem importing one of the Python modules”
- Py第十七问Importing a Python module works from command line, but not from PyCharm
- 32位centos运行yum报错:There was a problem importing one of the Python modules
- Importing and Exporting Data
- ABAP function exporting importing
- Importing Apache mod_rewrite Rules
- Importing video using Javacv
- ABAP EXPORTING IMPORTING
- 牛顿插值
- [BZOJ1606] [Usaco2008 Dec]Hay For Sale 购买干草
- Hadoop之MapReduce
- HDU 2018
- 二维码的生成细节和原理
- Importing `*` in Python
- Summary Ranges
- iOS动画之漂亮的时钟
- iOS敏捷开发之道,常用的宏定义总结
- HADOOP之HDFS
- Hibernate(九)实现一对一关联映射关系
- 股票学习10
- 硬件路由转发原理浅析-清晨补充
- [BZOJ3399] [Usaco2009 Mar]Sand Castle城堡