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用于url解码和中文解析的小脚本(python url decoder)
Aug 11 Python
跟老齐学Python之关于类的初步认识
Oct 11 Python
使用Protocol Buffers的C语言拓展提速Python程序的示例
Apr 16 Python
Python使用pymysql从MySQL数据库中读出数据的方法
Jul 25 Python
python使用epoll实现服务端的方法
Oct 16 Python
python+numpy按行求一个二维数组的最大值方法
Jul 09 Python
keras模型可视化,层可视化及kernel可视化实例
Jan 24 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
Feb 07 Python
使用python图形模块turtle库绘制樱花、玫瑰、圣诞树代码实例
Mar 16 Python
使用pycharm和pylint检查python代码规范操作
Jun 09 Python
python drf各类组件的用法和作用
Jan 12 Python
Python抖音快手代码舞(字符舞)的实现方法
Feb 07 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
如何在PHP中使用正则表达式进行查找替换
2013/06/13 PHP
一个经典的PHP验证码类分享
2014/11/18 PHP
PHP编写登录验证码功能 附调用方法
2016/05/19 PHP
PHP简单检测网址是否能够正常打开的方法
2016/09/04 PHP
php原生数据库分页的代码实例
2019/02/18 PHP
php设计模式之适配器模式原理、用法及注意事项详解
2019/09/24 PHP
JavaScript 计算图片加载数量的代码
2011/01/01 Javascript
autoPlay 基于jquery的图片自动播放效果
2011/12/07 Javascript
JS控制文本框textarea输入字数限制的方法
2013/06/17 Javascript
JavaScript实现多个重叠层点击切换效果的方法
2015/04/24 Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
2016/12/23 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
Angular.js中ng-if、ng-show和ng-hide的区别介绍
2017/01/20 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
JS全角与半角转化实例(分享)
2017/07/04 Javascript
JS数组交集、并集、差集的示例代码
2017/08/23 Javascript
JS实现的进制转换,浮点数相加,数字判断操作示例
2019/11/09 Javascript
vue router返回到指定的路由的场景分析
2020/11/10 Javascript
使用python调用浏览器并打开一个网址的例子
2014/06/05 Python
Python批量合并有合并单元格的Excel文件详解
2018/04/05 Python
对python 命令的-u参数详解
2018/12/03 Python
python paramiko利用sftp上传目录到远程的实例
2019/01/03 Python
Python 实现数据结构-堆栈和队列的操作方法
2019/07/17 Python
keras实现基于孪生网络的图片相似度计算方式
2020/06/11 Python
Python在后台自动解压各种压缩文件的实现方法
2020/11/10 Python
C面试题
2015/10/08 面试题
WebSphere面试题:在WebSphere里面如何部署一个应用
2015/08/02 面试题
护理自荐信范文
2013/10/05 职场文书
酒店大堂副理的职责范文
2014/02/13 职场文书
计算机维护专业推荐信
2014/02/27 职场文书
给校长的建议书
2014/03/12 职场文书
2015年秋季运动会广播稿
2015/08/19 职场文书
2016年中学端午节主题活动总结
2016/04/01 职场文书
js实现自动锁屏功能
2021/06/02 Javascript
vue+iview实现手机号分段输入框
2022/03/25 Vue.js
Android在Sqlite3中的应用及多线程使用数据库的建议
2022/04/24 Java/Android