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中使用百度音乐搜索的api下载指定歌曲的lrc歌词
Jul 18 Python
python脚本实现统计日志文件中的ip访问次数代码分享
Aug 06 Python
17个Python小技巧分享
Jan 23 Python
python实现自动网页截图并裁剪图片
Jul 30 Python
python实现名片管理系统
Nov 29 Python
python设置环境变量的作用和实例
Jul 09 Python
Pandas中DataFrame的分组/分割/合并的实现
Jul 16 Python
python将三维数组展开成二维数组的实现
Nov 30 Python
Python绘图实现显示中文
Dec 04 Python
python实现局域网内实时通信代码
Dec 22 Python
python实现扑克牌交互式界面发牌程序
Apr 22 Python
Django serializer优化类视图的实现示例
Jul 16 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
DOTA2游戏同人动画《龙之血》导演接受采访
2021/03/05 欧美动漫
php中记录用户访问过的产品,在cookie记录产品id,id取得产品信息
2011/05/04 PHP
PHP中捕获超时事件的方法实例
2015/02/12 PHP
Ubuntu 16.04下安装PHP 7过程详解
2017/03/28 PHP
Nigma vs Alliance BO5 第四场2.14
2021/03/10 DOTA
为JavaScript类型增加方法的实现代码(增加功能)
2011/12/29 Javascript
js 对小数加法精度处理示例说明
2013/12/27 Javascript
Javascript 遍历页面text控件详解
2014/01/06 Javascript
jquery 插件实现多行文本框[textarea]自动高度
2015/03/04 Javascript
原生js实现ajax方法(超简单)
2016/09/20 Javascript
原生js和css实现图片轮播效果
2017/02/07 Javascript
vue组件之Alert的实现代码
2017/10/17 Javascript
jquery引入外部CDN 加载失败则引入本地jq库
2018/05/23 jQuery
详解小程序如何改变onLoad的执行时机
2019/11/01 Javascript
python类中super()和__init__()的区别
2016/10/18 Python
浅谈Python基础之I/O模型
2017/05/11 Python
pytorch逐元素比较tensor大小实例
2020/01/03 Python
解决python中显示图片的plt.imshow plt.show()内存泄漏问题
2020/04/24 Python
将pymysql获取到的数据类型是tuple转化为pandas方式
2020/05/15 Python
Python改变对象的字符串显示的方法
2020/08/01 Python
解决margin 外边距合并问题
2019/07/03 HTML / CSS
在HTML5中使用MathML数学公式的简单讲解
2016/02/19 HTML / CSS
世界最大域名注册商:GoDaddy
2016/07/24 全球购物
美国打印机墨水和碳粉购物网站:QuikShip Toner
2018/08/29 全球购物
澳大利亚优质葡萄酒专家:Vintage Cellars
2019/01/08 全球购物
C/C++ 笔试、面试题目大汇总
2015/11/21 面试题
linux面试题参考答案(5)
2016/11/05 面试题
银行见习期自我鉴定
2014/01/29 职场文书
人事专员的岗位职责
2014/03/01 职场文书
办理信用卡收入证明范例
2014/09/13 职场文书
2014年民主评议党员个人总结
2014/09/24 职场文书
市场调研项目授权委托书范本
2014/10/04 职场文书
古诗文之爱国名句(77句)
2019/09/24 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python
Python+OpenCV实现图片中的圆形检测
2022/04/07 Python