建议十八:有节制的使用from...import语句
python提供了三种方式引入外部模块:
-
import语句
-
from...import...
-
__import__函数
使用的时候需要注意以下几点:
-
一般情况下尽量优先使用import a形式,如访问B时需要使用a.B的形式
-
有节制地使用from a import B形式,可以直接访问B
-
尽量避免使用from a import *,因为这会污染命名空间,并且无法清晰地表示导入了哪些对象
首先简单的了解下python的import机制。python在初始化运行环境的时候会预先加载一批内建模块到内存中,这些模块相关的信息被存放在sys.modules中,当加载一个模块的时候,解释器世嘉尚要完成以下动作:
-
在sys.modules中进行搜索看看该模块是否已经存在,如果存在,则将其导入到当前局部命名空间,加载结束
-
如果在sys.modules中找不到对应模块的名称,则为需要导入的模块创建一个字典对象,并将该对象信息插入sys.modules中
-
加载前确认是否需要对模块对应的文件进行编译,如果需要则先进行编译
-
执行动态加载,在当前模块的命名空间中执行编译后的字节码,并将其中所有的对象放入模块对应的字典中。
如果无节制的使用from a import ...会带来以下问题:
-
命名空间冲突
一般来说在非常明确不会造成明明冲突的前提下,以下几种情况下可以考虑使用from...import语句 -
当只需要导入部分属性或方法时
-
模块中的这些属性和方法访问频率较高导致使用“模块名.名称”的形式进行访问过于繁琐时
-
模块的文档明确说明需要使用from..import形式,导入的是一个包下面的子模块,且能够更为简单和便利时
-
循环嵌套导入的问题
c1.py: from c2 import g def x(): pass c2.py: from c1 import x def g(): pass
有时间可以试试上面的导入,会抛出ImportError异常,但是直接使用import就可以。
建议十九:优先使用absolute import来导入模块
相对导入:在不指明package名的情况相爱导入自己这个package的模块
绝对导入:指明顶层package名,python会在sys.path中寻找所有的顶层模块
加入有如下文件结构,其中app/sub1/string.py中定义了一个lower()方法。
app/
__init__.py
sub1/
__init__.py
mod1.py
string.py
sub2/
__init__.py
mod2.py
经验告诉我们,挡在mod1.py中import string之后,调用string.lower()方法时,会覆盖掉python自带的string模块中的方法。所以如果要使用python的String模块中的方法呢?
python2.5后为absolute import提供了一种新的机制,在模块中使用from _future_ import absolute_import语句进行说明后再进行导入,会禁用implicit relative,但是并不会禁掉explicit relative import。同时类似于linux,它还通过点号提供了一种显式进行relative import的方法,“.”表示当前目录,“..”表示当前目录的上一层目录。
相比于absolute import,relative import的问题比较多,因此推荐优先使用absolute import。
建议二十:i+=1 不等于 ++i
python的解释器会将++i操作解释为+(+i),其中+号表示证书符号,--i也类似。