簡體   English   中英

Python:在其中的模塊和類之間共享全局變量

[英]Python: Sharing global variables between modules and classes therein

我知道可以在 Python 中跨模塊共享全局變量。 但是,我想知道這在多大程度上是可能的以及為什么。 例如,

global_mod.py

x = None

mid_access_mod.py

from global_mod import *

class delta:
    def __init__(self):
        print x

bot_modif_mod.py

import mid_access_mod
import global_mod

class mew:
    def __init__(self):
        global_mod.x = 5

def main():
    m = mew()
    d = mid_access_mod.delta()

這將打印 None,即使所有模塊都共享全局變量 x。 為什么會這樣? 似乎 x 在 mid_access_mod.py 中被評估,然后由 mew() 在 bot_modif_mod.py 中分配。

發生這種情況是因為您使用的是不可變值(整數和無),並且導入變量就像按值傳遞事物,而不是通過引用傳遞事物。

如果您創建 global_mod.xa 列表,並操作它的第一個元素,它將按您的預期工作。

當您執行from global_mod import x ,您將在模塊中創建一個名稱x ,其值與xglobal_mod值相同。 對於函數和類之類的東西,這正如您所期望的那樣工作,因為人們(通常)以后不會重新分配這些名稱。

正如亞歷克斯指出的那樣,如果您使用import global_mod ,然后使用global_mod.x ,您將避免這個問題。 您在模塊中定義的名稱將是global_mod ,它總是涉及到你想要的模塊,然后使用屬性的訪問來獲得在x將讓你的最新值x

from whatever import *不是在您的代碼中使用的好習慣——它旨在用於(如果有的話)在交互式會話中作為保存一些輸入的快捷方式。 它基本上是在那個時間點“快照”模塊中的所有名稱——如果您重新綁定這些名稱中的任何一個,快照將變得陳舊,並且會接踵而至。 這只是您使用可悲的from ... import *構造來注冊的無法解決的混亂的開始。

想要我的建議嗎? 忘記你曾經聽說過那個結構存在,永遠不要再使用它。 使用import global_mod as m ,並始終使用后合格的名稱,如mx -合格的名字都這么多的更加便利,並在Python更強大,比單純的barenames,它甚至不是滑稽。 import語句的as m部分是完全可選的,基本上是為了簡潔而存在,或者有時是為了解決名稱沖突的一些問題;當你覺得它很方便時使用它,因為它沒有缺點,但不要如果您覺得沒有必要,則感到被迫或什至被敦促使用)。

我修改了示例以使用 x 的列表,並按照頂級答案中的建議列表分配 (x[0] = ..),並且打印返回相同的初始值(無)。這驗證了“來自 global_mod import *" 是一個副本,無論是否可變。

正如評論“import global_mod”中所建議的那樣,如果在mid_access_mod中使用“print global_mod.x =”。

正如 Ned Batchelder 所提到的,只有值是共享的,而不是實際的對象。 如果您想通過引用共享對象,那么您可能正在尋找Thread-Local Data

例如:

import threading

g = threading.local()
g.population = '7 Billion'

現在,無論何時您想要訪問或更改變量 g.population,您都會獲得它的更新值,前提是它與您試圖從中訪問它的線程相同。

在 Python 文檔中閱讀更多內容: https : //docs.python.org/3/library/threading.html#thread-local-data

要解決這個問題,只需將from global_mod import *更改為import global_mod

新的mid_access_mod.py將是:

import global_mod

class delta:
    def __init__(self):
        print global_mod.x

原因可以在這里找到。

由於引用和名稱綁定在 Python 中的工作方式,如果您想從該模塊外部更新模塊中的某個符號,例如 foo.bar,並讓其他導入代碼“看到”該更改,則必須導入 foo a某種方式。

暫無
暫無

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

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