阅读关于import
的内容时,笔者先就内心的一个疑惑——循环引用——做了一个小小测试。
测试代码为两个很小文件:
# a.py
from b import VAR_B
VAR_A = 'var_a'
print(VAR_B)
# b.py
from a import VAR_A
VAR_B = 'var_b'
print(VAR_A)
测试结果如下:
>python3 a.py
Traceback (most recent call last):
File "/Users/dd/learn/python/effective-python/a.py", line 3, in <module>
from b import VAR_B
File "/Users/dd/learn/python/effective-python/b.py", line 2, in <module>
from a import VAR_A
File "/Users/dd/learn/python/effective-python/a.py", line 3, in <module>
from b import VAR_B
ImportError: cannot import name 'VAR_B' from partially initialized module 'b' (most likely due to a circular import)
显然,Python是有做循环引用检测的,如果存在循环引用,代码执行时会抛出异常。(此处笔者有一个对自己过去认知的疑问:我印象中Python中循环引用是可以的,这印象来源于何处呢?笔者不深想,因为好的代码结构,是不推荐多个模块互相引用的。)
PEP8关于import
的建议,笔者并无更多思考,只在此处做一些搬运。
1、分行
# 对的
import os
import sys
# 不好的
import os, sys
# 可以的
from subprocess import Popen, PIPE
2、位置
import
语句,最好都放在文件开头。
这一条,笔者在Python标准库中有看到“不按规则”行事。
# Lib.http.client.py
# 第1446行
try:
import ssl
except ImportError:
pass
else:
class HTTPSConnection(HTTPConnection):
"This class allows communication via SSL."
# ...
示例代码来源于此:github.com/python/cpyt…
3、顺序
请按以下顺序进行导入:
- 标准库;
- 相关的第三方包;
- 本项目模块;
其中每一组之间,添加一个空行以示分割;每个组内,按字母顺序排列(笔者曾经很喜欢使用模块名称长度排序,我认为那样很好看)。
笔者最近工作中写C++较多,看到此处时也有去搜一下C++的include
风格推荐,有看到谷歌的风格。谷歌的工程师,对C++ include顺序的推荐,也是相似的。
来源链接:google.github.io/styleguide/…
建议顺序(Include headers in the following order):
- Related header(相关文件,即cc或cpp同名的那个头文件);
- C system headers(C系统头文件,笔者搜了一下,列表该在这个链接中:en.cppreference.com/w/c/header。…
- C++ standard library headers(C++标准库头文件);
- other libraries' headers(使用的其它库的头文件);
- your project's headers(自己项目中的内容)。
笔者曾经自学过一段时间golang
语言,我对go语言当中对import
的处理,是相当赞同的。go语言当中,可以使用go fmt
指令将导入内容做排序操作,且如果导入的模块未使用,会报错:
"fmt" imported and not used
4、路径
PEP8推荐使用绝对路径导入,这样会有两个好处:可读性相对较好且出现问题时报错信息更全面。但并非绝对,如果相对路径导入拥有更好可读性,也是可以选择相对路径的。
此处看似自相矛盾,但其实内里核心只是一条:一切都为可读性。
5、不要使用import *
如题。
6、小结
关于import
,笔者只整理到此处;甚至关于PEP8,也只到此处。其实文档中还有其它内容,比如逗号、注释等等,但本系列博客以书籍Effective Python作为基础,于是章节划分都尽量以书中内容为准。
笔者依然建议大家看看PEP8官方文档,它并不长。
总之,大家的Python代码风格,请尽量遵守PEP8;但别忘了,项目组的风格优先级高于PEP8。
毕竟我们的代码,读比写更多。