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使用win32com在百度空间插入html元素示例
Feb 20 Python
跟老齐学Python之赋值,简单也不简单
Sep 24 Python
Python中的测试模块unittest和doctest的使用教程
Apr 14 Python
Python使用urllib2模块实现断点续传下载的方法
Jun 17 Python
python实现识别相似图片小结
Feb 22 Python
Python中Collections模块的Counter容器类使用教程
May 31 Python
Python如何生成树形图案
Jan 03 Python
python调用摄像头显示图像的实例
Aug 03 Python
python实现一个点绕另一个点旋转后的坐标
Dec 04 Python
Python 多线程共享变量的实现示例
Apr 17 Python
django rest framework 自定义返回方式
Jul 12 Python
Python环境搭建过程从安装到Hello World
Feb 05 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
海河写的 Discuz论坛帖子调用js的php代码
2007/08/23 PHP
php打造属于自己的MVC框架
2012/03/07 PHP
php防止sql注入代码实例
2013/12/18 PHP
php 判断网页是否是utf8编码的方法
2014/06/06 PHP
thinkPHP商城公告功能开发问题分析
2016/12/01 PHP
详解PHP处理字符串类似indexof的方法函数
2017/06/11 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
2007/03/10 Javascript
使用jQuery的ajax功能实现的RSS Reader 代码
2009/09/03 Javascript
javascript学习笔记(五)正则表达式
2011/04/08 Javascript
基于JavaScript实现继承机制之调用call()与apply()的方法详解
2013/05/07 Javascript
javascript文件中引用依赖的js文件的方法
2014/03/17 Javascript
jquery实现动画菜单的左右滚动、渐变及图形背景滚动等效果
2015/08/25 Javascript
plupload+artdialog实现多平台上传文件
2016/07/19 Javascript
微信小程序 两种滑动方式(横向滑动,竖向滑动)详细及实例代码
2017/01/13 Javascript
Three.js实现3D机房效果
2018/12/30 Javascript
js中数组对象去重的两种方法
2019/01/18 Javascript
js实现的格式化数字和金额功能简单示例
2019/07/30 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&平移轮播效果
2019/08/16 Javascript
在antd中setFieldsValue和defaultVal的用法
2020/10/29 Javascript
[47:03]完美世界DOTA2联赛PWL S3 access vs LBZS 第一场 12.20
2020/12/23 DOTA
[54:43]DOTA2-DPC中国联赛 正赛 CDEC vs Dynasty BO3 第一场 2月22日
2021/03/11 DOTA
Tensorflow实现卷积神经网络用于人脸关键点识别
2018/03/05 Python
解决python opencv无法显示图片的问题
2018/10/28 Python
python异步存储数据详解
2019/03/19 Python
CSS3 please 跨浏览器的CSS3产生器
2010/03/14 HTML / CSS
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
来自Ocado的宠物商店:Fetch
2018/07/10 全球购物
优秀员工表扬信
2014/01/17 职场文书
初二生物教学反思
2014/02/03 职场文书
网络管理专业求职信
2014/03/15 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书
年终工作总结范文2014
2014/11/27 职场文书
美术教师求职信范文
2015/03/20 职场文书
2015年园林绿化工作总结
2015/05/23 职场文书
Centos环境下Postgresql 安装配置及环境变量配置技巧
2021/05/18 PostgreSQL
python 判断文件或文件夹是否存在
2022/03/18 Python