zoukankan      html  css  js  c++  java
  • python 全局变量的import机制

          在之前学习python设计模式(工厂模式实践篇),希望使用全局变量代替c++的宏完成服务自动注册功能时,遇到过一个问题,全局变量的定义和使用放在同一个可执行脚本中的问题。先把有问题的代码晒一下:

    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 # 接收到报文后,根据报文的内容,从db中获取到serverType,假设获取到的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())

        代码内已经加了调试的部分信息, 运行CreatFactory.py。调用DoWithA失败,提示AttributeError: 'str' object has no attribute 'DoWithA'。运行结果如下:

    
    

    D:Python27python.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']
    1
    ['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

     

         从运行的结果,可以看到:GLOBAL_class_dic 被定义了2次。有两个不同的id,第一次定义分配了一块内存,第二次不明原因的又重新分配了一块内存,然后服务的自动注册全部注册在这块内存中,等到main函数使用的使用,又使用的是第一次申请的内存,所以导致程序运行失败。那问题就来了,为什么会被重新又分配了一次?

         之所以会被重新定义一次全局变量,是因为在执行CreatFactory.py时,最开始定义了全局变量,此时该命名空间可使用的函数和变量打印:['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打印出可使用的函数和变量时,['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'],就没有GLOBAL_class_dic,程序发现没有,就又重新声明了一遍。似乎问题原因已经找到了。

        python在导入的时候,有2种场景,一种就是在文件前普通的import语句,还有一种就是特殊的场景:__main__模块是相对于Python的导入系统。在最开始运行CreatFactory.py文件时,__name__打印的值是__main__,而再子类再次导入时,会在当前命名空间查找是否已经导入__name__=CreatFactory,发现这个模块不存在,故此又导入了一遍,全局变量由此又被重新定义分配了内存,后期全局变量在子类业务的使用就都使用该值,而在main函数里,使用的又是当前的作用域内的第一次定义的全局变量。

      

  • 相关阅读:
    my97date与struts2的结合使用
    window.frames["detailFrm"].isSubmitting = true;//?起什么作用
    apache ant
    JodaTime 简介
    dbgrid中没有数据原因1
    网页 BODY的topMargin 和leftMargin
    在java类中定义log
    discuz论坛移动后,如果不能连接上数据库。可能是连接数据库的用户密码不正确。
    在后台对字符串进行转码
    [转] 我们的企业比日本少了什么
  • 原文地址:https://www.cnblogs.com/loleina/p/7469218.html
Copyright © 2011-2022 走看看