自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一種Python全局配置規(guī)范以及其魔改

開(kāi)發(fā) 后端
在Python中,模塊是天然的單例,模塊會(huì)在項(xiàng)目初始化后執(zhí)行一次,之后一般不重復(fù)執(zhí)行,符合單例模式的特點(diǎn)。因此,利用模塊的這一特性,將整個(gè)工程文件中需要配置的選項(xiàng)都配置到一個(gè)模塊中,在需要用的模塊中通過(guò)import導(dǎo)入,才是Python中全局配置正確打開(kāi)方式。

一種Python全局配置規(guī)范以及其魔改

一、模塊 or global

很多初學(xué)者有個(gè)誤區(qū),就是在Python中需要配置一個(gè)全局的參數(shù)時(shí),首先想到的是global關(guān)鍵字,而實(shí)際上global不是干這個(gè)事的,global的功能是在將局部作用域的變量聲明為全局的,這樣可以在局部修改全局的變量。

但這種用法其實(shí)非常不好,按照函數(shù)式的規(guī)范而言,純函數(shù)的輸入應(yīng)該只有輸入?yún)?shù)確定,不應(yīng)該在執(zhí)行過(guò)程中引用外部變量。并且,global也不是用來(lái)進(jìn)行全局配置用的。

在Python中,模塊是天然的單例,模塊會(huì)在項(xiàng)目初始化后執(zhí)行一次,之后一般不重復(fù)執(zhí)行,符合單例模式的特點(diǎn)。因此,利用模塊的這一特性,將整個(gè)工程文件中需要配置的選項(xiàng)都配置到一個(gè)模塊中,在需要用的模塊中通過(guò)import導(dǎo)入,才是Python中全局配置正確打開(kāi)方式。

雖然這種規(guī)范已經(jīng)在江茍(Django)等開(kāi)源框架中展示了無(wú)數(shù)遍,但“如何在Python中設(shè)置全局變量”這個(gè)問(wèn)題仍然是Python社區(qū)的月經(jīng)貼。

通過(guò)模塊配置全局變量的試?yán)缦?,在configs.py中定義CONFIG_A和CONFIG_B。在user.py中用import導(dǎo)入。

這個(gè)其實(shí)是Python中的基本操作了,本來(lái)是沒(méi)啥好講的,不過(guò)在這篇文章最后我展示了一種根據(jù)json配置的動(dòng)態(tài)模塊,供大家參考。

二、單例字典

在講模塊之前,我想談?wù)勎覈L試過(guò)另一種方式,就是自定義單例字典,具體做法是這樣的。

先繼承collections模塊中MutableMapping,并重寫(xiě)相關(guān)接口。這是在Python中自定義數(shù)據(jù)類(lèi)型的基本操作了,自定義完成后然后寫(xiě)一個(gè)裝飾器將繼承的類(lèi)轉(zhuǎn)化成單例的類(lèi)。

單例模式的寫(xiě)法可以看Stackoverflow上關(guān)于單例模式的高票回答。

我習(xí)慣采用第一種函數(shù)裝飾器的寫(xiě)法:

這種寫(xiě)法非常好理解,用一個(gè)類(lèi)變量instances保存該類(lèi)生成的實(shí)例,每次類(lèi)被調(diào)用的時(shí)候判斷一下這個(gè)類(lèi)是否在instances字典里,如果不在著生成一個(gè)實(shí)例并放入instances字典。

但這個(gè)寫(xiě)法有個(gè)問(wèn)題,裝飾后的返回的不是一個(gè)類(lèi),而是一個(gè)函數(shù),雖然Python語(yǔ)法講究一切皆對(duì)象,但函數(shù)是享受不到類(lèi)的諸如繼承之類(lèi)的特性的。

如果需要返回一個(gè)單例類(lèi)的話(huà)需要用元類(lèi)的寫(xiě)法,或者第四種類(lèi)裝飾器的寫(xiě)法。當(dāng)然,具體到這里而言,這個(gè)類(lèi)是繼承了一個(gè)MutableMapping的,不能再繼承別的元類(lèi)了,元類(lèi)的寫(xiě)法在這里不適用。

三、單例字典的問(wèn)題

用單例字典做全局配置看著比模塊炫酷,其實(shí)并沒(méi)那么好用。原因是單例模式自身的一個(gè)弊病,違背了單一職責(zé)原則,這個(gè)在相關(guān)設(shè)計(jì)模式的教程里有講到。而且,字典在這一塊還有個(gè)弊病就是根本不知道需要用到的key是不是存在字典中。

單例字典是我在項(xiàng)目初期引入,并在項(xiàng)目的迭代過(guò)程中給我造成最大困擾的一個(gè)東西,在開(kāi)始時(shí)幾乎將所有的配置都寫(xiě)入到這個(gè)字典中,然后在程序運(yùn)行中這個(gè)字典又被分散在程序各處的各個(gè)實(shí)例修改,運(yùn)行到后面根本不知道字典里有什么,字典里的某個(gè)內(nèi)容是否被修改過(guò)。不過(guò)由于GIL,倒是不需要考慮鎖的問(wèn)題,可能是唯一的一個(gè)幸事。

在后期將這個(gè)龐大的字典進(jìn)行重構(gòu),重構(gòu)的過(guò)程按照下面的方式進(jìn)行:

1、將各個(gè)類(lèi)中該字典的引用點(diǎn),由各個(gè)方法收攏到init方法。

不應(yīng)該

應(yīng)該

2、將各個(gè)引用點(diǎn)的名稱(chēng)統(tǒng)一。

不應(yīng)該

應(yīng)該

3、將子函數(shù)中直接引用單例字典的參數(shù)放到函數(shù)的參數(shù)列表中,由調(diào)用方獲取單例字典內(nèi)容,由傳參的方法傳入被調(diào)用函數(shù),這樣做是為了滿(mǎn)足函數(shù)式編程中純函數(shù)的原則。

不應(yīng)該這么用:

應(yīng)該這樣用

4、將單一的單例字典分成多個(gè)單例字典,并將部分單例字典轉(zhuǎn)換成模塊,這個(gè)就不舉例了。

四、動(dòng)態(tài)模塊

模塊的用法很簡(jiǎn)單,在一個(gè)文件里配置好,直接import就行。需要注意的是引用的入口最好在同一個(gè)地方。

不過(guò)模塊有個(gè)地方不好就是動(dòng)態(tài)修改不方便,具體到項(xiàng)目中去就是,該項(xiàng)目通過(guò)工廠(chǎng)模式生成了一系列產(chǎn)品,每個(gè)產(chǎn)品所需的配置參數(shù)都不一樣。

這里有個(gè)辦法就是每個(gè)產(chǎn)品都通過(guò)同一個(gè)模塊來(lái)配置,然后在初始化時(shí)根據(jù)以產(chǎn)品名稱(chēng)命名的一個(gè)json文件修改模塊的參數(shù)。這樣就可以達(dá)到引用模塊的方式不變,但模塊的內(nèi)容是根據(jù)json文件的內(nèi)容來(lái)配置的。

詳細(xì)的代碼見(jiàn)github,主要用來(lái)動(dòng)態(tài)修改模塊的語(yǔ)句如下:

其實(shí)就是通過(guò)setattr這個(gè)常用的給對(duì)象動(dòng)態(tài)的添加功能的函數(shù),d.tiems()是一個(gè)從json文件中讀取的字典對(duì)象。

五、動(dòng)態(tài)模塊的優(yōu)勢(shì)

現(xiàn)在,一個(gè)配置模塊的方案就成了導(dǎo)入configs模塊,調(diào)用update_config_by_name函數(shù),即動(dòng)態(tài)修改函數(shù),并按照相應(yīng)的json文件修改模塊的值。

相對(duì)于在每個(gè)類(lèi)初始化時(shí)直接調(diào)用json配置變量這種方案是有好處的,定義了configs模塊有助于代碼的靜態(tài)檢查,形成了一種像C語(yǔ)言中.h文件和.c文件的關(guān)系,在頭文件中定義相關(guān)的變量,在.c文件中實(shí)現(xiàn)或使用。這里就成了在configs模塊中定義變量,變量的值由json文件確定,然后在其他模塊中通過(guò)import實(shí)現(xiàn),并且這個(gè)東西是全局共享的。當(dāng)然,這個(gè)全局的意思指的是整個(gè)解釋器。

這段代碼還是有個(gè)坑,一般出現(xiàn)在單元測(cè)試中,來(lái)看兩段代碼:

 

在單元測(cè)試中由于deepcopy的問(wèn)題,根據(jù)導(dǎo)入的層級(jí)不一樣,CONFIG_X的值也發(fā)生了不一樣的改變,這是個(gè)還在研究的bug。 

責(zé)任編輯:龐桂玉 來(lái)源: Python中文社區(qū)
相關(guān)推薦

2022-01-26 20:01:24

管理工具knife4j

2020-12-09 10:15:34

Pythonweb代碼

2020-12-23 10:10:23

Pythonweb代碼

2022-06-22 09:44:41

Python文件代碼

2022-07-07 10:33:27

Python姿勢(shì)代碼

2018-04-16 09:43:39

2022-09-23 13:57:11

xxl-job任務(wù)調(diào)度中間件

2018-08-06 12:10:57

SparkRPC Server代碼

2017-01-22 16:35:02

iOSBlockCallback

2012-01-17 11:02:39

2023-07-18 18:10:04

2015-01-21 15:35:58

開(kāi)源

2023-06-02 15:26:37

光纖綜合布線(xiàn)

2015-08-31 09:27:21

語(yǔ)言界面UI

2015-08-03 09:36:01

賽迪翻譯

2017-06-22 16:46:45

2018-03-06 10:46:42

代碼Python買(mǎi)水果

2022-06-06 15:44:24

大數(shù)據(jù)數(shù)據(jù)分析思維模式

2010-06-07 09:29:21

云計(jì)算

2012-10-12 09:32:14

開(kāi)源云開(kāi)源云技術(shù)云標(biāo)準(zhǔn)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)