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超简单解决约瑟夫环问题
May 12 Python
浅谈python配置与使用OpenCV踩的一些坑
Apr 02 Python
Python爬虫获取图片并下载保存至本地的实例
Jun 01 Python
Python基于mysql实现学生管理系统
Feb 21 Python
python3的print()函数的用法图文讲解
Jul 16 Python
对Django中内置的User模型实例详解
Aug 16 Python
python-OpenCV 实现将数组转换成灰度图和彩图
Jan 09 Python
基于打开pycharm有带图片md文件卡死问题的解决
Apr 24 Python
python为什么会环境变量设置不成功
Jun 23 Python
Python操作MySQL数据库的示例代码
Jul 13 Python
关于python3.7安装matplotlib始终无法成功的问题的解决
Jul 28 Python
Python爬虫之爬取淘女郎照片示例详解
Jul 28 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
Zend公司全球首推PHP认证
2006/10/09 PHP
Zend Framework缓存Cache用法简单实例
2016/03/19 PHP
浅谈PHP错误类型及屏蔽方法
2017/05/27 PHP
用javascript控制iframe滚动的代码
2007/04/10 Javascript
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
2008/12/25 Javascript
js选择并转移导航菜单示例代码
2014/08/19 Javascript
JS日期格式化之javascript Date format
2015/10/01 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
2015/10/29 Javascript
基于Node.js实现nodemailer邮件发送
2016/01/26 Javascript
深入理解js函数的作用域与this指向
2016/05/28 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
2017/01/18 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
d3.js入门教程之数据绑定详解
2017/04/28 Javascript
layui 图片上传+表单提交+ Spring MVC的实例
2019/09/21 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
python str与repr的区别
2013/03/23 Python
简单上手Python中装饰器的使用
2015/07/12 Python
深入解析Python中的线程同步方法
2016/06/14 Python
python PyTorch参数初始化和Finetune
2018/02/11 Python
python使用json序列化datetime类型实例解析
2018/02/11 Python
python树莓派红外反射传感器
2019/01/21 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
2019/02/08 Python
浅析PEP570新语法: 只接受位置参数
2019/10/15 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
Python子进程subpocess原理及用法解析
2020/07/16 Python
scrapy结合selenium解析动态页面的实现
2020/09/28 Python
viagogo波兰票务平台:演唱会、体育比赛、戏剧门票
2018/04/23 全球购物
牦牛毛户外探险服装:Kora
2019/02/08 全球购物
荣耀俄罗斯官网:HONOR俄罗斯
2020/10/31 全球购物
初入社会应届生求职信
2013/11/18 职场文书
大专学生推荐信范文
2013/11/19 职场文书
大学生职业规划前言模板
2013/12/27 职场文书
保险公司年会主持词
2014/03/22 职场文书
保险公司增员口号
2015/12/25 职场文书
python中的被动信息搜集
2021/04/29 Python
浅谈resultMap的用法及关联结果集映射
2021/06/30 Java/Android