python 全局變量的import機(jī)制介紹
先把有問(wèn)題的代碼曬一下:
IServer.py
from abc import ABCMeta, abstractmethod print __name__ class IServer: def __init__(self): pass @abstractmethod def DoWithA(self): pass @abstractmethod def DoWithB(self): pass
IServer_A.py
import IServer serverType ='1001' print __name__ dir() from CreatFactory import GLOBAL_class_dic dir() class IServer_A(IServer.IServer): def __init__(self): pass def DoWithA(self): print 'Server_A do with interface A' def DoWithB(self): print 'Server_A do with interface B' global GLOBAL_class_dic print 'the id of GLOBAL_class_dic in A is:',id(GLOBAL_class_dic) GLOBAL_class_dic[serverType] = IServer_A print 'GLOBAL_class_dic in a is:', GLOBAL_class_dic
IServer_B.py
import IServer serverType ='1002'from CreatFactory import GLOBAL_class_dic print __name__ class IServer_B(IServer.IServer): def __init__(self): pass def DoWithA(self): print 'Server_B do with interface A' def DoWithB(self): print 'Server_B do with interface B' print 'the id of GLOBAL_class_dic in B is:',id(GLOBAL_class_dic) GLOBAL_class_dic[serverType] = IServer_B print 'GLOBAL_class_dic in b is:', GLOBAL_class_dic
CreatFactory.py
#coding:UTF-8 import os; import sys; import threading from misc import * global GLOBAL_class_dic GLOBAL_class_dic ={1:1} print 'GLOBAL_class_dic in define is:', GLOBAL_class_dic print 'the id of GLOBAL_class_dic in define is:', id(GLOBAL_class_dic) dir() import IServer_A import IServer_B def CreateServer(serverType): global GLOBAL_class_dic print 'GLOBAL_class_dic in use is:', GLOBAL_class_dic print 'the id of GLOBAL_class_dic in USE is:', id(GLOBAL_class_dic) if GLOBAL_class_dic.has_key(serverType): return GLOBAL_class_dic[serverType] else: return 'no' if __name__ == '__main__': pass # 接收到報(bào)文后,根據(jù)報(bào)文的內(nèi)容,從db中獲取到serverType,假設(shè)獲取到的serverType=1001 print 'main' print 'GLOBAL_class_dic in main A is:', GLOBAL_class_dic serverType = '1002' server = CreateServer(serverType) print 'GLOBAL_class_dic in main B is:', GLOBAL_class_dic print 'server :',server server.DoWithA(server())
代碼內(nèi)已經(jīng)加了調(diào)試的部分信息, 運(yùn)行CreatFactory.py。調(diào)用DoWithA失敗,提示AttributeError: 'str' object has no attribute 'DoWithA'。運(yùn)行結(jié)果如下:
D:\Python27\python.exe "D:/DesignMode/Server --00/CreatFactory.py" GLOBAL_class_dic in define is: {1: 1} the id of GLOBAL_class_dic in define is: 36230176 ['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading'] IServer IServer_A ['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'] GLOBAL_class_dic in define is: {1: 1} the id of GLOBAL_class_dic in define is: 36230032 ['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading'] ['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'] ['GLOBAL_class_dic', 'IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'] IServer_B the id of GLOBAL_class_dic in B is: 36230032 GLOBAL_class_dic in b is: {1: 1, '1002': <class IServer_B.IServer_B at 0x022C2ED8>} ['GLOBAL_class_dic', 'IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'] the id of GLOBAL_class_dic in A is: 36230032 GLOBAL_class_dic in a is: {1: 1, '1002': <class IServer_B.IServer_B at 0x022C2ED8>, '1001': <class IServer_A.IServer_A at 0x02273420>} main GLOBAL_class_dic in main A is: {1: 1} GLOBAL_class_dic in use is: {1: 1} the id of GLOBAL_class_dic in USE is: 36230176 GLOBAL_class_dic in main B is: {1: 1} server : no Traceback (most recent call last): File "D:/DesignMode/Server --00/CreatFactory.py", line 38, in <module> server.DoWithA(server()) AttributeError: 'str' object has no attribute 'DoWithA' Process finished with exit code 1
從運(yùn)行的結(jié)果,可以看到:GLOBAL_class_dic 被定義了2次。有兩個(gè)不同的id,第一次定義分配了一塊內(nèi)存,第二次不明原因的又重新分配了一塊內(nèi)存,然后服務(wù)的自動(dòng)注冊(cè)全部注冊(cè)在這塊內(nèi)存中,等到main函數(shù)使用的使用,又使用的是第一次申請(qǐng)的內(nèi)存,所以導(dǎo)致程序運(yùn)行失敗。那問(wèn)題就來(lái)了,為什么會(huì)被重新又分配了一次?
之所以會(huì)被重新定義一次全局變量,是因?yàn)樵趫?zhí)行CreatFactory.py時(shí),最開(kāi)始定義了全局變量,此時(shí)該命名空間可使用的函數(shù)和變量打印:['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading',然后在import IServer_A,在IServer_A.py中,import IServer后,在from CreatFactory import GLOBAL_class_dic打印出可使用的函數(shù)和變量時(shí),['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'],就沒(méi)有GLOBAL_class_dic,程序發(fā)現(xiàn)沒(méi)有,就又重新聲明了一遍。似乎問(wèn)題原因已經(jīng)找到了。
python在導(dǎo)入的時(shí)候,有2種場(chǎng)景,一種就是在文件前普通的import語(yǔ)句,還有一種就是特殊的場(chǎng)景:__main__模塊是相對(duì)于Python的導(dǎo)入系統(tǒng)。在最開(kāi)始運(yùn)行CreatFactory.py文件時(shí),__name__打印的值是__main__,而再子類再次導(dǎo)入時(shí),會(huì)在當(dāng)前命名空間查找是否已經(jīng)導(dǎo)入__name__=CreatFactory,發(fā)現(xiàn)這個(gè)模塊不存在,故此又導(dǎo)入了一遍,全局變量由此又被重新定義分配了內(nèi)存,后期全局變量在子類業(yè)務(wù)的使用就都使用該值,而在main函數(shù)里,使用的又是當(dāng)前的作用域內(nèi)的第一次定義的全局變量。
相關(guān)文章
Python編程實(shí)現(xiàn)從字典中提取子集的方法分析
這篇文章主要介紹了Python編程實(shí)現(xiàn)從字典中提取子集的方法,結(jié)合實(shí)例形式對(duì)比分析了Python采用字典推導(dǎo)式與序列轉(zhuǎn)換實(shí)現(xiàn)字典提取子集的相關(guān)操作技巧與優(yōu)缺點(diǎn),需要的朋友可以參考下2018-02-02Django用戶認(rèn)證系統(tǒng) Web請(qǐng)求中的認(rèn)證解析
這篇文章主要介紹了Django用戶認(rèn)證系統(tǒng) Web請(qǐng)求中的認(rèn)證解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Python如何安裝mysql數(shù)據(jù)庫(kù)模塊
這篇文章主要介紹了Python如何安裝mysql數(shù)據(jù)庫(kù)模塊問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07用Python中的wxPython實(shí)現(xiàn)最基本的瀏覽器功能
這篇文章主要介紹了用Python中的wxPython實(shí)現(xiàn)基本的瀏覽器功能,本文來(lái)自于IBM官方網(wǎng)站開(kāi)發(fā)者文檔,需要的朋友可以參考下2015-04-04