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实现的几个常用排序算法实例
Jun 16 Python
对Python中type打开文件的方式介绍
Apr 28 Python
python面试题小结附答案实例代码
Apr 11 Python
Python2.7版os.path.isdir中文路径返回false的解决方法
Jun 21 Python
python GUI库图形界面开发之PyQt5日期时间控件QDateTimeEdit详细使用方法与实例
Feb 27 Python
python新手学习可变和不可变对象
Jun 11 Python
python3的pip路径在哪
Jun 23 Python
Django REST Swagger实现指定api参数
Jul 07 Python
Python3 搭建Qt5 环境的方法示例
Jul 16 Python
分享unittest单元测试框架中几种常用的用例加载方法
Dec 02 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
Feb 05 Python
python数据可视化使用pyfinance分析证券收益示例详解
Nov 20 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
晶体管来复再生式二管收音机
2021/03/02 无线电
PHP CURL模拟GET及POST函数代码
2010/04/25 PHP
php实现读取和写入tab分割的文件
2015/06/01 PHP
CodeIgniter表单验证方法实例详解
2016/03/03 PHP
Ubuntu 16.04下安装PHP 7过程详解
2017/03/28 PHP
php批量转换文件夹下所有文件编码的函数类
2017/08/06 PHP
PHP仿tp实现mvc框架基本设计思路与实现方法分析
2018/05/23 PHP
PHP连接SQL server数据库测试脚本运行实例
2020/08/24 PHP
jQuery中parentsUntil()方法用法实例
2015/01/07 Javascript
为jQuery-easyui的tab组件添加右键菜单功能的简单实例
2016/10/10 Javascript
详解Angular的数据显示优化处理
2016/12/26 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
分享十三个最佳JavaScript数据网格库
2017/04/07 Javascript
js canvas实现QQ拨打电话特效
2017/05/10 Javascript
jQuery实现碰到边缘反弹的动画效果
2018/02/24 jQuery
java遇到微信小程序 "支付验证签名失败" 问题解决
2019/12/22 Javascript
vue 组件销毁并重置的实现
2020/01/13 Javascript
Vue.js原理分析之nextTick实现详解
2020/09/07 Javascript
原生JS生成指定位数的验证码
2020/10/28 Javascript
使用Python绘制图表大全总结
2017/02/11 Python
python安装cx_Oracle模块常见问题与解决方法
2017/02/21 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
Python中@property的理解和使用示例
2019/06/11 Python
tensorboard显示空白的解决
2020/02/15 Python
利用python绘制数据曲线图的实现
2020/04/09 Python
python中JWT用户认证的实现
2020/05/18 Python
定制别致的瑜伽垫:Sugarmat
2019/06/21 全球购物
德国高尔夫商店:Golfshop.de
2019/06/22 全球购物
俄罗斯有趣和原创礼物网上商店:MagicMag
2019/08/01 全球购物
eharmony澳大利亚:网上约会服务
2020/02/29 全球购物
2014年教师业务工作总结
2014/12/19 职场文书
继承公证书格式
2015/01/26 职场文书
2015年材料员工作总结
2015/04/30 职场文书
学子宴致辞大全
2015/07/27 职场文书
MySQL实例精讲单行函数以及字符数学日期流程控制
2021/10/15 MySQL
python中的getter与setter你了解吗
2022/03/24 Python