go和python变量赋值遇到的一个问题


Posted in Python onAugust 31, 2017

平时写得多的是python,最近看了一点go,今天碰到了一个问题,和大家分享一下

package main

import "fmt"

type student struct {
  Name string
  Age int
}

func pase_student() {
  m := make(map[string]*student)
  stus := []student{
    {Name: "zhou", Age: 24},
    {Name: "li", Age: 23},
    {Name: "wang", Age: 22},
  }
  for _, stu := range stus {
    m[stu.Name] = &stu
  }
  fmt.Println(m["zhou"].Name)
}

func main() {
  pase_student()
}

代码很简单,大家可以思考一下会打印出什么。

time.sleep(60)  # 思考

结果是 wang !,惊喜不惊喜!遍历赋值啊同学们,这么简单的操作都能出幺蛾子,WTF!

为什么是 wang 呢?
你tm给我
解释解释
什么是惊喜

for循环的时候,变量stu的指针是不变的,每次循环仅仅是对student结构体的 值 拷贝,上面的for循环和下面是一样的:

var stu student 
for _, stu = range stus {
 m[stu.Name] = &stu
}

所以 &stu 自始至终都是一个地址,变化的是这个地址上存储的值。 &stu 最终存储的值是 student{Name: "wang", Age: 22} 结构体,所以拿出来的是 wang 。

可以将 m 打出来看一下:

map[zhou:0xc42000a260 li:0xc42000a260 wang:0xc42000a260]

验证了我们上面的想法,大家的value都是同一个地址。

看到这里,如果是一个日常写c,c++等强类型语言的同学可能会说,神经病啊!这有什么好说的!不就是这样的吗!请原谅我,我日常写python的 [捂脸]。

从上面的例子可以看出来,在go中,变量名是 存储地址的名字 。它在编译时绑定已经完成,运行时是不可以改变的,你只能改变地址中存储的值。

而在python中,变量是对象的名字,运行时变量可以绑定到任意的对象上。如下所示:

In [4]: a = 123456

In [5]: id(a)
Out[5]: 4426596208

In [6]: a = 1234567

In [7]: id(a)
Out[7]: 4426592592

注意:由于python对int类型实现了 小整数对象池 ,不要用 0-255 的整数做实验,不然你得到id会是一样的。

也就是说,当你循环一个list的时候,每次得到的是不同对象,变量指向了不同的地址:

In [9]: for i in [2222, 2223, 2224]:
  ...:   print(id(i))
  ...:
4426596208
4426592336
4426596080

上面这段代码,python为我们创建了3个 PyIntObject , i 只是他们的名字。而在go中,可以认为只有一个object,值变化了3次。

python中说的 赋值就是建立一个对象的引用 ,是实话。

Python 相关文章推荐
python连接mysql并提交mysql事务示例
Mar 05 Python
进一步探究Python的装饰器的运用
May 05 Python
在Python中使用全局日志时需要注意的问题
May 06 Python
Python中exit、return、sys.exit()等使用实例和区别
May 28 Python
Python 实现一个颜色色值转换的小工具
Dec 06 Python
Django查询数据库的性能优化示例代码
Sep 24 Python
Python利用lxml模块爬取豆瓣读书排行榜的方法与分析
Apr 15 Python
python实现智能语音天气预报
Dec 02 Python
Python文件读写w+和r+区别解析
Mar 26 Python
PageFactory设计模式基于python实现
Apr 14 Python
Python任务调度模块APScheduler使用
Apr 15 Python
如何用python反转图片,视频
Apr 24 Python
理解Python中的绝对路径和相对路径
Aug 30 #Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
Aug 30 #Python
python递归打印某个目录的内容(实例讲解)
Aug 30 #Python
python-opencv在有噪音的情况下提取图像的轮廓实例
Aug 30 #Python
关于python的list相关知识(推荐)
Aug 30 #Python
Python编程实现正则删除命令功能
Aug 30 #Python
Python删除Java源文件中全部注释的实现方法
Aug 30 #Python
You might like
Yii实现文章列表置顶功能示例
2016/10/18 PHP
php基于dom实现读取图书xml格式数据的方法
2017/02/03 PHP
Jquery Uploadify上传带进度条的简单实例
2014/02/12 Javascript
jquery 获取 outerHtml 包含当前节点本身的代码
2014/10/30 Javascript
JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍
2016/05/19 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
利用Bootstrap实现表格复选框checkbox全选
2016/12/21 Javascript
jquery实现自定义图片裁剪功能【推荐】
2017/03/08 Javascript
在Vue项目中使用snapshot测试的具体使用
2019/04/16 Javascript
vue项目中使用fetch的实现方法
2019/04/25 Javascript
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
微信小程序webview与h5通过postMessage实现实时通讯的实现
2019/08/20 Javascript
微信小程序webSocket的使用方法
2020/02/20 Javascript
vue中activated的用法
2021/01/03 Vue.js
[03:40]2014DOTA2国际邀请赛 B神专访:躲箭真的很难
2014/07/13 DOTA
在Python中用get()方法获取字典键值的教程
2015/05/21 Python
在arcgis使用python脚本进行字段计算时是如何解决中文问题的
2015/10/18 Python
用Python将动态GIF图片倒放播放的方法
2016/11/02 Python
Python实现的多叉树寻找最短路径算法示例
2018/07/30 Python
Python tkinter label 更新方法
2018/10/11 Python
Python简单I/O操作示例
2019/03/18 Python
python调用pyaudio使用麦克风录制wav声音文件的教程
2019/06/26 Python
pycharm设置当前工作目录的操作(working directory)
2020/02/14 Python
python3 logging日志封装实例
2020/04/08 Python
Python run()函数和start()函数的比较和差别介绍
2020/05/03 Python
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
荷兰之家英文站:Holland at Home
2016/10/26 全球购物
全球知名的珠宝首饰品牌:Kay Jewelers
2018/02/11 全球购物
Black Halo官方网站:购买连衣裙、礼服和连体裤
2018/06/13 全球购物
酒吧创业计划书
2014/01/18 职场文书
校园摄影活动策划方案
2014/02/05 职场文书
酒店餐厅2014重阳节活动策划方案
2014/09/16 职场文书
保送生自荐信范文
2015/03/26 职场文书
2015年食品安全工作总结
2015/05/15 职场文书
2015年音乐教师个人工作总结
2015/05/20 职场文书
观看安全警示教育片心得体会
2016/01/15 职场文书