python中from module import * 的一个坑

 更新时间:2014年07月20日 15:32:28   投稿:hebedich  
from module import *把module中的成员全部导到了当前的global namespace,访问起来就比较方便了。当然,python style一般不建议这么做,因为可能引起name conflict。

但还有另外一个问题 - 你以为你修改了某个变量,其实,被from module import *后的那个并没有被更新,非常危险,因为程序有可能还可以正常运行, 只不过结果错了,到了production才被发现就比较惨了。

举个例子:

你定义了一些变量在base模块中:

# reference data type
class Demo:
 def __init__(self, name):
  self.name = name
demo = Demo('Demo')

# primitive type
foo = 1

然后在一个模块中用from  module import 的方式读它:

from base import *
def read():
    print 'reference data id: ' + str(id(demo))
    print 'reference data value : ' + demo.name

    print 'primitive data id: ' + str(id(foo))
    print 'primitive data value: ' + str(foo)

在另外一个模块中写它:

import base

def write():
 print "\nOriginal:"
 print "Original reference data id: " + str(id(base.demo))
 base.demo.name = "Updated Demo" # this will reflect that change
 #base.demo = base.Demo("Updated Demo") # this won't relfect the change
 print "Original data id: " + str(id(base.foo))
 base.foo = 1000
 print "Original data id after assignment: " + str(id(base.foo))

然后先写,后读,看写的内容是否有效:

import read
import write

print "before write"
read.read()

write.write()

print "\nafter write"
read.read()

结论是没有,原因是:

当你用from module import时,其实是copy了一份reference或者pointer,指向一份内存,var和module.var都指向同一份内存
当你修改module.var时,其实你是让它指向了另外一份内存,此时var和module.var指向的是不同的内存
所以,虽然module.var的值变了,var还是指向原来那份内存,原来的值
这个对于object,比较容易理解,你可以直接修改object里的值,这个是有效的,但是当你指向另外一个object时就无效了。 对于primitive类型来讲,其实也是一个道理,因为每次赋值,都是让其指向一个不同的内存地址,而不是inplace修改已有的那份内存 -  这个很容易验证:

In [1]: a = 10

In [2]: id(a)
Out[2]: 20429204

In [3]: a = 100

In [4]: id(a)
Out[4]: 20430108

所以,建议是除非是一个quick and dirty的脚本,否则不要使用from module import *!

例子: https://github.com/baiyanhuang/blog/tree/master/arena/python/from_module_import

相关文章

  • Pycharm使用时会出现的问题之cv2无法安装解决

    Pycharm使用时会出现的问题之cv2无法安装解决

    这篇文章主要介绍了Pycharm使用时会出现的问题之cv2无法安装解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 如何利用Python实现简单C++程序范围分析

    如何利用Python实现简单C++程序范围分析

    这篇文章主要介绍了如何利用Python实现简单C++程序范围分析,文章以举例说明及过程实现思路的方式展开讲解,具有一定的的参考价值,需要的小伙伴可以参考一下,希望对你有所帮助
    2022-02-02
  • python 自定义异常和异常捕捉的方法

    python 自定义异常和异常捕捉的方法

    今天小编就为大家分享一篇python 自定义异常和异常捕捉的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-10-10
  • python实践项目之监控当前联网状态详情

    python实践项目之监控当前联网状态详情

    介绍一个利用Python监控当前联网状态情况的python代码,它可以清楚地知道,你的电脑网络是否是链接成功或失败,下面小编带大家来一起学习它
    2019-05-05
  • 基于Python编写一个点名器的示例代码

    基于Python编写一个点名器的示例代码

    想起小学的时候老师想点名找小伙伴回答问题的时候,老师竟斥巨资买了个点名器。今日无聊便敲了敲小时候老师斥巨资买的点名器,希望对大家有帮助
    2022-07-07
  • 如何在Windows环境下安装PyMySQL(已安装Anaconda)

    如何在Windows环境下安装PyMySQL(已安装Anaconda)

    这篇文章主要介绍了如何在Windows环境下安装PyMySQL问题(已安装Anaconda),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • Python3环境安装Scrapy爬虫框架过程及常见错误

    Python3环境安装Scrapy爬虫框架过程及常见错误

    这篇文章主要介绍了Python3环境安装Scrapy爬虫框架过程及常见错误 ,本文给大家介绍的非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-07-07
  • python中内置函数range详解

    python中内置函数range详解

    Python内置函数range()是一个用于生成一系列连续的整数的函数,它常用于循环结构中,用于指定循环的次数或迭代的范围,这篇文章主要介绍了python之内置函数range,需要的朋友可以参考下
    2023-07-07
  • python元组和字典的内建函数实例详解

    python元组和字典的内建函数实例详解

    这篇文章主要介绍了python元组和字典的内建函数,结合实例形式详细分析了Python元组和字典的各种常见内建函数功能与相关使用技巧,需要的朋友可以参考下
    2019-10-10
  • 使用Python检查CPU型号并弹出警告信息

    使用Python检查CPU型号并弹出警告信息

    本教程将指导你如何编写一个Python程序,该程序能够在启动时检查计算机的CPU型号,如果检测到CPU型号包含“I3”,则会弹出一个警告窗口,感兴趣的小伙伴跟着小编一起来看看吧
    2024-12-12

最新评论