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使用PIL库实现验证码图片的方法
Mar 11 Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 Python
Python实现在线暴力破解邮箱账号密码功能示例【测试可用】
Sep 06 Python
Python字符编码与函数的基本使用方法
Sep 30 Python
Python 使用with上下文实现计时功能
Mar 09 Python
Python 修改列表中的元素方法
Jun 26 Python
Django实现网页分页功能
Oct 31 Python
python+Selenium自动化测试——输入,点击操作
Mar 06 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
Jun 23 Python
django models里数据表插入数据id自增操作
Jul 15 Python
OpenCV-Python实现轮廓拟合
Jun 08 Python
Python Django ORM连表正反操作技巧
Jun 13 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 Static关键字实用方法
2010/06/04 PHP
PHP学习笔记之字符串编码的转换和判断
2014/05/22 PHP
PHP中的use关键字概述
2014/07/23 PHP
js replace 与replaceall实例用法详解
2013/08/03 Javascript
JS实现OCX控件的事件响应示例
2014/09/17 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
javascript实现框架高度随内容改变的方法
2015/07/23 Javascript
jquery+css3实现网页背景花瓣随机飘落特效
2015/08/17 Javascript
JS创建事件的三种方法(实例代码)
2016/05/12 Javascript
100行代码理解和分析vue2.0响应式架构
2017/03/09 Javascript
jQuery开源组件BootstrapValidator使用详解
2017/06/29 jQuery
Vue中父组件向子组件通信的方法
2017/07/11 Javascript
vue 注册组件的使用详解
2018/05/05 Javascript
Javascript实现购物车功能的详细代码
2018/05/08 Javascript
vue插件draggable实现拖拽移动图片顺序
2018/12/01 Javascript
vue如何获取自定义元素属性参数值的方法
2019/05/14 Javascript
详解vue中$nextTick和$forceUpdate的用法
2019/12/11 Javascript
vue 全局封装loading加载教程(全局监听)
2020/11/05 Javascript
[10:39]DOTA2上海特级锦标赛音乐会纪录片
2016/03/21 DOTA
Python MD5文件生成码
2009/01/12 Python
安装Python的web.py框架并从hello world开始编程
2015/04/25 Python
python3+PyQt5+Qt Designer实现堆叠窗口部件
2018/04/20 Python
深度辨析Python的eval()与exec()的方法
2019/03/26 Python
Python2.7版os.path.isdir中文路径返回false的解决方法
2019/06/21 Python
Python列表list常用内建函数实例小结
2019/10/22 Python
python列表推导式操作解析
2019/11/26 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
如何通过Python实现RabbitMQ延迟队列
2020/11/28 Python
如何用 Python 制作 GitHub 消息助手
2021/02/20 Python
关于HTML5你必须知道的28个新特性,新技巧以及新技术
2012/05/28 HTML / CSS
HTML5之SVG 2D入门1—SVG(可缩放矢量图形)概述
2013/01/30 HTML / CSS
香港迪士尼乐园酒店预订:Hong Kong Disneyland Hotels
2017/05/02 全球购物
英国马莎百货印度官网:Marks & Spencer印度
2020/10/08 全球购物
暑假家长评语大全
2014/04/17 职场文书
服务理念标语
2014/06/18 职场文书
Java中API的使用方法详情
2022/04/06 Java/Android