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实现可将字符转换成大写的tcp服务器实例
Apr 29 Python
python处理二进制数据的方法
Jun 03 Python
基于Python如何使用AIML搭建聊天机器人
Jan 27 Python
举例讲解Python设计模式编程中对抽象工厂模式的运用
Mar 02 Python
读取本地json文件,解析json(实例讲解)
Dec 06 Python
numpy.ndarray 交换多维数组(矩阵)的行/列方法
Aug 02 Python
Windows系统下PhantomJS的安装和基本用法
Oct 21 Python
Python学习笔记基本数据结构之序列类型list tuple range用法分析
Jun 08 Python
Python简单处理坐标排序问题示例
Jul 11 Python
django 信号调度机制详解
Jul 19 Python
Python更换pip源方法过程解析
May 19 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
Feb 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 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
2014/06/12 PHP
一个图片地址分解程序(用于PHP小偷程序)
2014/08/23 PHP
PHP采集静态页面并把页面css,img,js保存的方法
2014/12/23 PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
2016/11/16 PHP
PHP+mysql防止SQL注入的方法小结
2019/04/27 PHP
用显卡加速,轻松把笔记本打造成取暖器的办法!
2013/04/17 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
2013/04/24 Javascript
浅谈angularJS 作用域
2015/07/05 Javascript
详解页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
2015/12/03 Javascript
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
2016/08/04 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
使用node.js对音视频文件加密的实例代码
2017/08/30 Javascript
vue.js响应式原理解析与实现
2020/06/22 Javascript
JS中数据结构之栈
2019/01/01 Javascript
微信小程序的授权实现过程解析
2019/08/02 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
Python编写电话薄实现增删改查功能
2016/05/07 Python
python引入不同文件夹下的自定义模块方法
2018/10/27 Python
Python发送邮件功能示例【使用QQ邮箱】
2018/12/04 Python
Python 获取div标签中的文字实例
2018/12/20 Python
PyQt5 对图片进行缩放的实例
2019/06/18 Python
Django 解决开发自定义抛出异常的问题
2020/05/21 Python
keras中的卷积层&池化层的用法
2020/05/22 Python
python 发送get请求接口详解
2020/11/17 Python
CSS Grid布局教程之网格单元格布局
2014/12/30 HTML / CSS
写clone()方法时,通常都有一行代码,是什么?
2012/10/31 面试题
怎样写好自荐信和推荐信
2013/12/26 职场文书
商业门面租房协议书
2014/11/25 职场文书
大专护理专业自荐信
2015/03/25 职场文书
《家世》读后感:看家训的力量
2019/12/30 职场文书
python 算法题——快乐数的多种解法
2021/05/27 Python
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android
Python matplotlib安装以及实现简单曲线的绘制
2022/04/26 Python
pytorch实现加载保存查看checkpoint文件
2022/07/15 Python
mysql通过group by分组取最大时间对应数据的两种有效方法
2022/09/23 MySQL
js基于div丝滑实现贝塞尔曲线
2022/09/23 Javascript