2016-08-30 62 views
2

doctest文檔有a section about execution context。 我的閱讀是模塊中的全局變量爲每個文檔字符串中的測試進行淺度複製,但不在文檔字符串內的測試之間重置。在文檔測試中修改全局變量

基於這樣的描述,我還以爲下面的文檔測試將通過:

X = 1 


def f(): 
    """Function F. 

    >>> X 
    1 
    >>> f() 
    2 
    >>> X 
    2 
    """ 
    global X 
    X = 2 
    return X 


def g(): 
    """Function G. 

    >>> g() 
    1 
    >>> X 
    1 
    """ 
    return X 

但不要使用以下測試通過!

X = 1 


def f(): 
    """Function F. 

    >>> X 
    1 
    >>> f() 
    2 
    >>> X 
    1 
    """ 
    global X 
    X = 2 
    return X 


def g(): 
    """Function G. 

    >>> g() 
    2 
    >>> X 
    1 
    """ 
    return X 

似乎全局變量跨文檔測試共享? 但只在函數調用內?

爲什麼這是由此產生的行爲? 這是否與具有與執行上下文分離的全局變量字典的函數有關?

回答

0

不完全。雖然全局變量是淺層複製的,但實際上您看到的是全局變量的範圍(使用關鍵字global)以及它在Python中如何在模塊級別上運行。您可以通過在分配後立即在功能f內輸入pdb.set_trace()來觀察此情況(X = 2)。

$ python -m doctest foo.py 
> /tmp/foo.py(18)f() 
-> return X 
(Pdb) bt 
    /usr/lib/python2.7/runpy.py(162)_run_module_as_main() 
-> "__main__", fname, loader, pkg_name) 
    /usr/lib/python2.7/runpy.py(72)_run_code() 
-> exec code in run_globals 
    /usr/lib/python2.7/doctest.py(2817)<module>() 
-> sys.exit(_test()) 
    /usr/lib/python2.7/doctest.py(2808)_test() 
-> failures, _ = testmod(m) 
    /usr/lib/python2.7/doctest.py(1911)testmod() 
-> runner.run(test) 
    /usr/lib/python2.7/doctest.py(1454)run() 
-> return self.__run(test, compileflags, out) 
    /usr/lib/python2.7/doctest.py(1315)__run() 
-> compileflags, 1) in test.globs 
    <doctest foo.f[1]>(1)<module>() 
-> f() 
> /tmp/foo.py(18)f() 
-> return X 
(Pdb) pp X 
2 

是,該值是f範圍內確實2,但讓我們來看看它的全局變量。我們來看看它們在當前幀和幀中的比較。

(Pdb) id(globals()) 
140653053803048 # remember this number, and we go up a frame 
(Pdb) u 
> <doctest foo.f[1]>(1)<module>() 
-> f() 
(Pdb) id(globals()) 
140653053878632 # the "shallow" clone 
(Pdb) X 
1 
(Pdb) c 

嗯哼,你可以看到,他們實際上不是一回事,那X確實1並沒有得到改變,因爲全局有通過文檔測試這個原因產生的<doctest doc.f>模塊內。讓我們繼續。

(Pdb) id(globals()) 
140653053803048 # hey look, is the SAME number we remember 
(Pdb) u 
> <doctest foo.g[0]>(1)<module>() 
-> g() 
(Pdb) id(globals()) 
140653053872960 # note how this is a different shallow clone 

所以你其實看到的是,文檔測試中的全局變量是不一樣的一個作爲一個視頻源(因此g將返回2因爲X真的是在模塊中通過f改變了這裏,但不在doctest模塊的淺拷貝範圍中),儘管它最初是從模塊中複製的,但是這些更改沒有反映回底層模塊,因爲這是global關鍵字在模塊級別運行的方式,而不是跨模塊。