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下载懒人图库JavaScript特效
May 28 Python
深入理解python多进程编程
Jun 12 Python
python机器学习理论与实战(一)K近邻法
Jan 28 Python
python实现excel读写数据
Mar 02 Python
python验证码识别教程之滑动验证码
Jun 04 Python
Python高斯消除矩阵
Jan 02 Python
python实现大文本文件分割
Jul 22 Python
如何解决python多种版本冲突问题
Oct 13 Python
python爬虫用scrapy获取影片的实例分析
Nov 23 Python
python利用appium实现手机APP自动化的示例
Jan 26 Python
用Python实现Newton插值法
Apr 17 Python
python基础之爬虫入门
May 10 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
一条久听不愿放下的DIY森海MX500,三言两语话神奇
2021/03/02 无线电
了解咖啡雨林联盟认证 什么是雨林认证 雨林认证是什么意思
2021/03/05 新手入门
php录入页面中动态从数据库中提取数据的实现
2006/10/09 PHP
PHP 时间转换Unix时间戳代码
2010/01/22 PHP
window+nginx+php环境配置 附配置搭配说明
2010/12/29 PHP
php模拟asp中的XmlHttpRequest实现http请求的代码
2011/03/24 PHP
深入理解PHP原理之错误抑制与内嵌HTML分析
2011/05/02 PHP
ThinkPHP基于PHPExcel导入Excel文件的方法
2014/10/15 PHP
完美解决thinkphp唯一索引重复时出错的问题
2017/03/31 PHP
PHP mysqli事务操作常用方法分析
2017/07/22 PHP
可实现多表单提交的javascript函数
2007/08/01 Javascript
jQuery中document与window以及load与ready 区别详解
2014/12/29 Javascript
Bootstrap网格系统详解
2016/04/26 Javascript
jQuery基础知识点总结(必看)
2016/05/31 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件
2018/06/19 Javascript
JS实现点击按钮可实现编辑功能
2018/07/03 Javascript
Echart折线图手柄触发事件示例详解
2018/12/16 Javascript
vue实现行列转换的一种方法
2019/08/06 Javascript
微信小程序如何通过用户授权获取手机号(getPhoneNumber)
2020/01/21 Javascript
three.js利用射线Raycaster进行碰撞检测
2020/03/12 Javascript
[13:39]2014 DOTA2华西杯精英邀请赛 5 25 NewBee VS DK第一场
2014/05/26 DOTA
浅谈python迭代器
2017/11/08 Python
python使用wxpy实现微信消息防撤回脚本
2019/04/29 Python
python实现单链表的方法示例
2019/09/03 Python
Python实现平行坐标图的绘制(plotly)方式
2019/11/22 Python
Python模块future用法原理详解
2020/01/20 Python
python中remove函数的踩坑记录
2021/01/04 Python
土建专业大学生自荐信范文
2014/04/09 职场文书
机房搬迁方案
2014/05/01 职场文书
求职信结尾怎么写
2014/05/26 职场文书
计生专干事迹
2014/05/28 职场文书
2014年幼儿园保育工作总结
2014/12/02 职场文书
离婚答辩状怎么写
2015/05/22 职场文书
python开发人人对战的五子棋小游戏
2022/05/02 Python
解决spring.thymeleaf.cache=false不起作用的问题
2022/06/10 Java/Android