python中from module import * 的一个坑


Posted in Python onJuly 20, 2014

但还有另外一个问题 - 你以为你修改了某个变量,其实,被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

Python 相关文章推荐
python 写的一个爬虫程序源码
Feb 28 Python
django使用xlwt导出excel文件实例代码
Feb 06 Python
python使用jieba实现中文分词去停用词方法示例
Mar 11 Python
Python读取excel指定列生成指定sql脚本的方法
Nov 28 Python
深入浅析Python2.x和3.x版本的主要区别
Nov 30 Python
详解python项目实战:模拟登陆CSDN
Apr 04 Python
将python文件打包成EXE应用程序的方法
May 22 Python
对Django中的权限和分组管理实例讲解
Aug 16 Python
python 模拟创建seafile 目录操作示例
Sep 26 Python
python匿名函数lambda原理及实例解析
Feb 07 Python
python中K-means算法基础知识点
Jan 25 Python
详解解决jupyter不能使用pytorch的问题
Feb 18 Python
用python代码做configure文件
Jul 20 #Python
python中的内置函数getattr()介绍及示例
Jul 20 #Python
Python实现的生成自我描述脚本分享(很有意思的程序)
Jul 18 #Python
Python中使用 Selenium 实现网页截图实例
Jul 18 #Python
Python中使用PyHook监听鼠标和键盘事件实例
Jul 18 #Python
python中使用pyhook实现键盘监控的例子
Jul 18 #Python
python使用pyhook监控键盘并实现切换歌曲的功能
Jul 18 #Python
You might like
php的控制语句
2006/10/09 PHP
最令PHP初学者们头痛的十四个问题
2007/01/15 PHP
PHP中HTTP方式下的Gzip压缩传输方法举偶
2007/02/15 PHP
php 上传文件类型判断函数(避免上传漏洞 )
2010/06/08 PHP
php的array数组和使用实例简明教程(容易理解)
2014/03/20 PHP
PHP实现驼峰样式字符串(首字母大写)转换成下划线样式字符串的方法示例
2017/08/10 PHP
redis+php实现微博(二)发布与关注功能详解
2019/09/23 PHP
jQuery EasyUI API 中文文档 - ProgressBar 进度条
2011/09/29 Javascript
js解析与序列化json数据(二)序列化探讨
2013/02/01 Javascript
HTML5之lang属性与dir属性的详解
2013/06/19 Javascript
jQuery Ajax使用实例
2015/04/16 Javascript
js倒计时小实例(多次定时)
2016/12/08 Javascript
JS多文件上传的实例代码
2017/01/11 Javascript
javascript表达式和运算符详解
2017/02/07 Javascript
Element-ui tree组件自定义节点使用方法代码详解
2018/09/17 Javascript
详解nodejs 开发企业微信第三方应用入门教程
2019/03/12 NodeJs
基于Express框架使用POST传递Form数据
2019/08/10 Javascript
如何用JS模拟实现数组的map方法
2020/07/30 Javascript
Nuxt.js的路由跳转操作(页面跳转nuxt-link)
2020/11/06 Javascript
夯基础之手撕javascript继承详解
2020/11/09 Javascript
[01:03:37]Secret vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
在 Django/Flask 开发服务器上使用 HTTPS
2014/07/03 Python
python实现解数独程序代码
2017/04/12 Python
Python最火、R极具潜力 2017机器学习调查报告
2017/12/11 Python
Python实现的朴素贝叶斯分类器示例
2018/01/06 Python
Python把对应格式的csv文件转换成字典类型存储脚本的方法
2019/02/12 Python
Python 分发包中添加额外文件的方法
2019/08/16 Python
Python列表list操作相关知识小结
2020/01/29 Python
基于pycharm实现批量修改变量名
2020/06/02 Python
python爬虫scrapy基本使用超详细教程
2021/02/20 Python
NBA德国官方网上商店:NBA Store德国
2018/04/13 全球购物
Grow Gorgeous美国官网:只要八天,体验唤醒毛囊后新生的茂密秀发
2018/06/04 全球购物
内业资料员岗位职责
2014/01/04 职场文书
打架检讨书
2015/01/27 职场文书
2016年小学圣诞节活动总结
2016/03/31 职场文书
Netty结合Protobuf进行编解码的方法
2021/06/26 Java/Android