簡體   English   中英

如何從子包訪問“全局”變量?

[英]How to access 'global' variable from subpackage?

我目前正在嘗試發布一些更大的項目。 這就是我決定使用子模塊的原因。 看一下項目結構:

/sandbox              
    __init.py__
    constants.py

    /sub1
        __init__.py
        foo.py

在我的constants.py文件中,我聲明了一個全局變量:

MYGLOBAL = 42

我想在foo.py中使用它的值。 該文件有 2 個用於測試的函數:

def foofunc():
    return 'I am foo.'

def constfunc():
    return 'I am {MYGLOBAL}.'

另外,我將這段代碼放入/sandbox/sub1/__init__.py

from .foo import *
from sandbox.constants import *

現在,當我使用我的解釋器時,我嘗試像這樣使用這兩個函數:

>> import sandbox.sub1
>> sandbox.sub1.foofunc()
'I am foo.'
>> sandbox.sub1.MYGLOBAL
42
>> sandbox.sub1.constfunc()
NameError: name 'MYGLOBAL' is not defined

據我了解,全局變量與函數位於同一命名空間中,但不知何故 function 看不到它。

我怎樣才能訪問它? Python 版本是 3.6。

謝謝!

“全局”變量在Python中並不是真正的全局變量,僅在定義它們的模塊的命名空間中可用。

您應該在foo.py導入constants ,以便可以將MYGLOBAL用作constants模塊對象的屬性:

from sandbox import constants
def constfunc():
    return f'I am {constants.MYGLOBAL}.'

對這個非常好的問題的遲到回答(已投票)。

這是一件事,可以讓您更好地了解正在發生的事情:

>>> sandbox.sub1.constfunc.__module__
'sandbox.sub1.foo'

>>> sandbox.sub1.constfunc.__globals__['MYGLOBAL']
KeyError: 'MYGLOBAL'

>>> sandbox.sub1.foo.MYGLOBAL = 5

>>> sandbox.sub1.constfunc.__globals__['MYGLOBAL']
5

>>> sandbox.sub1.constfunc()
'I am 5'

換句話說,

“這個 function 實際上屬於哪個模塊,從而決定它可以使用哪些模塊全局變量?”

您錯誤地認為它是sandbox.sub1 ,但它實際上是sandbox.sub1.foo 原因是因為函數的“父模塊”攜帶了 function object,即使這個 function object 被復制到另一個模塊的“工作區”。

有了這種理解,您可以做幾件事。 一個是根據這里的另一個答案。 另一種解決方案可能是在__init__.py中執行此操作:

from . import foo
from .. import constants
foo.MYGLOBAL = constants.MYGLOBAL

等等

有趣的事情要注意:

  1. 需要注意的一件事是from X import Y as Z語法實際上等同於說Z = XY 這是一個重要的見解,因為它可以幫助您認識到 Z 本身並不是一個“參考”:如果您更改 XY,Z 將不會自動更新

    如果將 X 中的 Y 更改為另一個值,並且想要更新 Z,則需要使用“from X import Y as Z”語法重新導入它。

  2. 有趣的是,你不能簡單地做:

     sandbox.sub1.constfunc.__module__ = sandbox.constants

    並簡單地期望將函數的模塊全局變量“替換”為sandbox.constants的變量。 這樣做的原因似乎是constfunc.__module__屬性只是原始父模塊的“副本”,更改它不會影響綁定到 function 的實際父模塊(即,它不會動態地“重新綁定” function 到另一個模塊;但是,由於這是一個內部變量,它可能會在未來的 python 版本中發生變化。誰知道呢。不要依賴它。)

    此外, __module__屬性不用於為 function 創建constfunc.__globals__字典; 這似乎總是直接反映“父模塊”的全局字典。 因此,簡單地替換sandbox.sub1.constfunc.__module__變量不會自動替換constfunc.__globals__字典,但更新sandbox.sub1.foo會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM