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实现监控linux性能及进程消耗性能的方法
Jul 25 Python
Python基础之函数用法实例详解
Sep 10 Python
在Django中进行用户注册和邮箱验证的方法
May 09 Python
Python中functools模块函数解析
Mar 12 Python
pandas DataFrame数据转为list的方法
Apr 11 Python
Python使用 Beanstalkd 做异步任务处理的方法
Apr 24 Python
django的登录注册系统的示例代码
May 14 Python
python模块导入的细节详解
Dec 10 Python
浅析PyTorch中nn.Linear的使用
Aug 18 Python
Windows10下 python3.7 安装 facenet的教程
Sep 10 Python
Python如何存储数据到json文件
Mar 09 Python
Pycharm安装并配置jupyter notebook的实现
May 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
nginx+php-fpm配置文件的组织结构介绍
2012/11/07 PHP
利用PHP内置SERVER开启web服务(本地开发使用)
2020/01/22 PHP
PHP数据源架构模式之表入口模式实例分析
2020/01/23 PHP
javascript 函数使用说明
2010/04/07 Javascript
web的各种前端打印方法之jquery打印插件PrintArea实现网页打印
2013/01/09 Javascript
详解 javascript中offsetleft属性的用法
2015/11/11 Javascript
分享我的jquery实现下拉菜单心的
2015/11/29 Javascript
JS+CSS3实现超炫的散列画廊特效
2016/07/16 Javascript
Web前端框架Angular4.0.0 正式版发布
2017/03/28 Javascript
JS表格组件神器bootstrap table使用指南详解
2017/04/12 Javascript
vue.js与element-ui实现菜单树形结构的解决方法
2018/04/21 Javascript
详解Vue This$Store总结
2018/12/17 Javascript
JavaScript 预解析的4种实现方法解析
2019/09/03 Javascript
TensorFlow.js 微信小程序插件开始支持模型缓存的方法
2020/02/21 Javascript
vue单元格多列合并的实现
2020/11/26 Vue.js
Nest.js 授权验证的方法示例
2021/02/22 Javascript
Python的函数嵌套的使用方法
2014/01/24 Python
python threading模块操作多线程介绍
2015/04/08 Python
Python封装shell命令实例分析
2015/05/05 Python
Python线程指南详细介绍
2017/01/05 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
python3.5绘制随机漫步图
2018/08/27 Python
Python中的heapq模块源码详析
2019/01/08 Python
通过python爬虫赚钱的方法
2019/01/29 Python
python scipy卷积运算的实现方法
2019/09/16 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
2020/04/24 Python
Python如何爬取qq音乐歌词到本地
2020/06/01 Python
python中的时区问题
2021/01/14 Python
python中K-means算法基础知识点
2021/01/25 Python
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
2012/12/13 HTML / CSS
马来西亚领先的在线礼品店:Giftr
2018/08/23 全球购物
优秀毕业生事迹材料
2014/02/12 职场文书
体育教师个人的自我评价
2014/02/16 职场文书
高校自主招生教师推荐信
2015/03/23 职场文书
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技