python引用問題

1. 絕對引用,相對引用(absolute_import and relative import)
package/__init__.py
pachage/lala.py
pachage/sys.py

假設在lala.py中import sys,是引用的當前目錄的sys, 仍是標準庫裏的sys?來看一下python

lala.py函數

import sys
print str(sys)

 

sys.py, __init__.py都是空文件便可ui

看一下執行結果spa

bogon:package licong$ python -m package.lala
<module 'package.sys' from 'package/sys.pyc'>

 

能夠知道,python是按照sys.path的優先級去尋找的模塊,若是找到就中止加載,而sys.path排在第一個的就是當前目錄,因此這就是所謂的隱式的相對引用。

好在python2.5中咱們後提供了一種修改這種行爲的方法,來看一下code

lala.py修改成blog

from __future__ import absolute_import
import sys
print str(sys)

來看一下結果get

bogon:package licong$ python -m package.lala
<module 'sys' (built-in)>

 

區別只是添加了from __future__ import absolute_import這句話it

若是咱們想用當前目錄的sys模塊怎麼辦?能夠經過顯示的相對引用來解決。class

lala.py修改成import

from __future__ import absolute_import
import sys
from . import sys as haha
print str(sys)
print str(haha)

 

bogon:package licong$ python -m package.lala
<module 'sys' (built-in)>
<module 'package.sys' from 'package/sys.pyc'>

 



總結一下包中的幾種引用方法,仍是以例子中的文件結構舉例

import package.sys 絕對引用
import package.sys 絕對引用且綁定別名
from package import sys 可替代的絕對引用
import sys 隱式的相對引用 
from . import sys 顯示的相對引用

2. 循環導入問題

c1.py

from c2 import g
def x():
    pass

c2.py

from c1 import x
def g():
    pass


上面這兩個文件執行任何一個文件都會報錯,緣由拿c1.py舉例

1.執行c1,
2.c1第一行須要引用c2中的g,執行c2
3.c2第一行引用c1中的x,執行c1
4.因爲c1並無執行完成,x並不存在
5.報錯

再舉一個更好的例子

a.py:

print "a in"
import sys
print "b imported: %s" % ("b" in sys.modules, )
import b
print "a out"

 


b.py:

print "b in"
import a
print "b out"
x = 3

 

執行a.py

$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
b out
a out

 

若是在a.py中添加
print b.x

則會報錯

緣由是, x只有在b out後纔會存在,而a out後就會執行print b.x,而a out 是在b out 以前的。


解決方法:
1 延遲import

c1.py

from c2 import g
def x():
    return g()
print x()

 


c2.py

def g():
    return 123
from c1 import x

 



可是,這樣修改的前提是g函數不會依賴c1

2. import到寫到函數內部

c1.py

def x():
    from c2 import g
    return g()
print x()

 



c2.py

def g():
    from c1 import x 
    return 123

 



這樣只有函數執行時,纔會加載響應模塊,可是若是有多個函數依賴其餘模塊,就須要寫多遍,很是蠢。

3. 包
首先要明確,若是不是在包中,是不應出現相對引用這種狀況的。
若是是在包中,上面這個問題是有解決方法的(由於包是一個總體,包的每一個組件單獨執行沒有任何意義,而非包每一個文件是能夠獨立執行的)


假設包結構是
package/__init__.py
package/a.py
package/b.py

解決方案1 
使用import而不要使用from import

a.py

import package.b
def x():
    pass
def haha():
    print package.b.g()

b.py

import package.a
def g():
    return 123


能夠看到,成功了

>>> import package.a
>>> package.a
<module 'package.a' from 'package/a.pyc'>
>>> package.a.haha()
123
>>> 

 


解決方案2
把from import 寫到__init__.py中
__init__.py

from . import a, b

 

a.py

import package
def x():
    pass

def haha():
    print package.b.g()

 

b.py

import package
def g():
    return 123

結果是同樣的

相關文章
相關標籤/搜索