簡體   English   中英

Python中全局變量的頻率?

[英]Frequency of global variables in python?

Stack Overflow對於python中的全局變量有很多疑問,對於來自其他語言的人來說似乎引起了一些困惑。 范圍界定規則並不能像其他背景的許多人所期望的那樣完全起作用。

同時,代碼不是在類級別而是在模塊級別組織的。 因此,當所有內容不一定都包含在類中時,可以在模塊級變量中進入否則將在成員變量中找到的狀態。

所以我的問題是2部分:

1)我應該避免使用全局變量(特別是從函數內部設置它們並使用global關鍵字)嗎?

2)如果#1是“是”,那么是否存在可以預期使用的通用模式?

我在一個有很多不同語言的地方工作,我想減輕混亂並確保pythonistas以后不會討厭我。

感謝您的建設性意見。

我強烈建議您閱讀此博客文章,標題為Singletons及其在Python中的問題 這使我重新考慮了對全局變量的使用。 一些選擇語錄:

但是要當心。 僅僅因為您沒有實現單例設計模式,並不意味着您避免了單例的核心問題。 單例的核心問題是全局共享狀態。 單例只不過是一個美化的全局變量,在Java之類的語言中,有很多原因使您想要使用單例之類的東西。 在Python中,單身人士有一些不同之處,它的名字很純真,可以掩蓋血腥的細節:模塊。

沒錯,伙計們:Python模塊是單例。 而且它也存在單例模式相同的問題,只是情況稍差一些。

這是具有這種共享狀態可能導致的問題的一個示例:

為了不討論不相關的內容,讓我們看一下標准庫中的模塊之一,即mimetypes模塊。

看一看:

inited = False

def init(files=None):
    global inited
    db = MimeTypes()
    ...

這是Python隨附的mimetypes模塊中的實際代碼,只是刪除了更多細節。 關鍵是,存在共享狀態。 共享狀態是一個布爾型標志,如果模塊已初始化,則為True;否則,則為False。 現在,這種特殊情況可能並沒有那么大的問題(請相信我),因為mimetypes會初始化自身,但是您可以看到init函數有一個files參數。 如果將文件列表傳遞給該函數,它將使用來自那些文件的mime信息重新初始化內存中的mime數據庫。 現在想象一下,如果您有兩個使用兩種不同來源初始化mimetypes的庫,那將會發生什么……

這是一個足夠普遍的模式,我自己完成了……但是例如,一種更好的方式是: init返回實現所有方法的類的實例,而代碼的其他部分可以init為獲得具有不同參數且不會干擾前者的其他實例。 “缺點”是您必須將此實例傳遞給任何不想初始化新實例的代碼,但是“缺點”的好處是它使您的依賴關系顯而易見。

總之,簡而言之,我會盡量避免使用它,但是如果您對具有隱式單例的代碼沒問題,那就去做吧。

簡而言之,是的,您應該避免使用global關鍵字。 它可能是出於某種原因而使用語言,但是我通常認為它是一種代碼味道-如果您希望保持某種狀態,請將其封裝在類中。 這遠沒有使用global脆弱。

我對您的其他問題說了這句話,所以這是我的2分:

Python是面向對象的,但您不必使用它。 但是,如果您選擇這樣做,則可以利用Class的這種機制來保存一些屬性:

class Config():
"""
hold some vars for example.
"""
def __init__(self):
    self.CONFIG_LOG_FILE_DIR='/tmp2/ozn/venus_mon_log/'
    self.DATE_FORMAT="%Y%m%d"
    #self.FILE_NAME_BASE_TEMPLATE=eval('datetime.datetime.now().strftime(self.DATE_FORMAT)')+'-venus_utilization.log'
    self.FILE_NAME_BASE_TEMPLATE='venus_utilization.log'
    self.FILE_NAME=self.CONFIG_LOG_FILE_DIR+self.FILE_NAME_BASE_TEMPLATE
    self.MAX_FILE_SIZE=1024*1024*50 # in Byte, 50 in MB.

您可以創建一個實例,使您可以訪問屬性:

   cfg = Config()

然后使用以下命令訪問它們:

   cfg.MAX_FILE_SIZE

甚至更改它們:

   cfg.MAX_FILE_SIZE=50000 
   cfg.MAX_FILE_SIZE=calculateNewSize() 

依此類推...您還可以執行以下操作:

 # this will print all items that an instance has    
 if options.debug:
    print "DEBUG INFO:"
    for k,v in vars(cfg).iteritems():
        print k,v

全局變量並不是真正的禁忌,只是您必須記住在使用它們之前在函數中將它們聲明為全局變量。 在我看來,這實際上使它們更加清晰,因為用戶會看到您顯式使用了全局變量。

我會更擔心非pythonista使用者不了解python全局變量,修改您的代碼並且未添加適當的全局聲明。

暫無
暫無

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

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