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 相关文章推荐
linux 下实现python多版本安装实践
Nov 18 Python
python中threading超线程用法实例分析
May 16 Python
python 排序算法总结及实例详解
Sep 28 Python
Python中int()函数的用法浅析
Oct 17 Python
python统计中文字符数量的两种方法
Jan 31 Python
python之pyqt5通过按钮改变Label的背景颜色方法
Jun 13 Python
使用python3批量下载rbsp数据的示例代码
Dec 20 Python
Python命名空间及作用域原理实例解析
Aug 12 Python
Pandas DataFrame求差集的示例代码
Dec 13 Python
关于Python错误重试方法总结
Jan 03 Python
matplotlib 使用 plt.savefig() 输出图片去除旁边的空白区域
Jan 05 Python
pandas取dataframe特定行列的实现方法
May 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
php开启安全模式后禁用的函数集合
2011/06/26 PHP
php数组函数序列之prev() - 移动数组内部指针到上一个元素的位置,并返回该元素值
2011/10/31 PHP
解决php表单重复提交实现方法
2015/09/29 PHP
php中yii框架实例用法
2020/12/22 PHP
IE和Firefox在JavaScript应用中的兼容性探讨
2008/04/01 Javascript
JavaScript 错误处理与调试经验总结
2010/08/10 Javascript
javaScript(JS)替换节点实现思路介绍
2013/04/17 Javascript
一个JS的日期格式化算法示例
2013/07/31 Javascript
js setTimeout 常见问题小结
2013/08/13 Javascript
Javascript 颜色渐变效果的实现代码
2013/10/01 Javascript
Javascript Ajax异步读取RSS文档具体实现
2013/12/12 Javascript
JavaScript String 对象常用方法详解
2016/05/13 Javascript
ionic实现带字的toggle滑动组件
2016/08/27 Javascript
详解JavaScript权威指南之对象
2016/09/27 Javascript
详解axios在node.js中的post使用
2017/04/27 Javascript
js和jquery中获取非行间样式
2017/05/05 jQuery
layui分页效果实现代码
2017/05/19 Javascript
VUE DOM加载后执行自定义事件的方法
2018/09/07 Javascript
浅谈angular2子组件的事件传递(任意组件事件传递)
2018/09/30 Javascript
浅谈Vue.use到底是什么鬼
2020/01/21 Javascript
Javascript原生ajax请求代码实例
2020/02/20 Javascript
Vue 打包的静态文件不能直接运行的原因及解决办法
2020/11/19 Vue.js
Python装饰器decorator用法实例
2014/11/10 Python
python简单实现刷新智联简历
2016/03/30 Python
python实现批量图片格式转换
2020/06/16 Python
python简单的三元一次方程求解实例
2020/04/02 Python
Visual-Click葡萄牙:欧洲领先的在线眼镜商
2020/02/17 全球购物
设计部经理的岗位职责
2013/11/16 职场文书
教育科研先进个人材料
2014/01/26 职场文书
财务出纳岗位职责
2014/02/03 职场文书
洗发露广告词
2014/03/14 职场文书
党员干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
领导干部作风建设总结
2014/10/23 职场文书
实习指导老师意见
2015/06/04 职场文书
python中os.path.join()函数实例用法
2021/05/26 Python
PostgreSQL逻辑复制解密原理解析
2022/09/23 PostgreSQL