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 相关文章推荐
使用Protocol Buffers的C语言拓展提速Python程序的示例
Apr 16 Python
python实现逆波兰计算表达式实例详解
May 06 Python
常见python正则用法的简单实例
Jun 21 Python
python实现kNN算法
Dec 20 Python
Python打印“菱形”星号代码方法
Feb 05 Python
python读取指定字节长度的文本方法
Aug 27 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
Feb 07 Python
使用wxpy实现自动发送微信消息功能
Feb 28 Python
解决pycharm不能自动补全第三方库的函数和属性问题
Mar 12 Python
Python3操作YAML文件格式方法解析
Apr 10 Python
python实现最短路径的实例方法
Jul 19 Python
python pyg2plot的原理知识点总结
Feb 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
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
PHP实现使用DOM将XML数据存入数组的方法示例
2017/09/27 PHP
Laravel实现短信注册的示例代码
2018/05/29 PHP
PHP使用mongoclient简单操作mongodb数据库示例
2019/02/08 PHP
JavaScript中令你抓狂的魔术变量
2006/11/30 Javascript
js倒计时小程序
2013/11/05 Javascript
JS替换字符串中字符即替换全部而不是第一个
2014/06/04 Javascript
Js 正则表达式知识汇总
2014/12/02 Javascript
javascript制作sql转换为stringBuffer的小工具
2015/04/03 Javascript
jquery判断复选框选中状态以及区分attr和prop
2015/12/18 Javascript
BootStrap智能表单实战系列(八)表单配置json详解
2016/06/13 Javascript
扩展jquery easyui tree的搜索树节点方法(推荐)
2016/10/28 Javascript
JS匿名函数类生成方式实例分析
2016/11/26 Javascript
jquery实现下拉框左右选择功能
2017/02/21 Javascript
深入理解Nodejs Global 模块
2017/06/03 NodeJs
基于node下的http小爬虫的示例代码
2018/01/11 Javascript
解决layui的使用以及针对select、radio等表单组件不显示的问题
2019/09/05 Javascript
vue + elementUI实现省市县三级联动的方法示例
2019/10/29 Javascript
python实现K最近邻算法
2018/01/29 Python
实用自动化运维Python脚本分享
2018/06/04 Python
tensorflow 获取变量&打印权值的实例讲解
2018/06/14 Python
pyqt5的QComboBox 使用模板的具体方法
2018/09/06 Python
基于Python实现剪切板实时监控方法解析
2019/09/11 Python
python框架flask表单实现详解
2019/11/04 Python
史泰博(Staples)中国官方网站:办公用品一站式采购
2016/09/05 全球购物
JAVA的事件委托机制和垃圾回收机制
2014/09/07 面试题
高级文秘工作总结的自我评价
2013/09/28 职场文书
商务英语专业求职信范文
2014/01/28 职场文书
开服装店计划书
2014/08/15 职场文书
作风转变心得体会
2014/09/02 职场文书
党员个人查摆剖析材料
2014/10/16 职场文书
告诉你创业计划书的8个实用技巧
2019/07/12 职场文书
2019年幼儿园管理条例范本!
2019/07/17 职场文书
创业计划书之溜冰场
2019/10/25 职场文书
导游词之阳朔遇龙河
2019/12/16 职场文书
oracle数据库去除重复数据
2022/05/20 Oracle