鱼C论坛

 找回密码
 立即注册
查看: 2108|回复: 5

[已解决]函数内数据被改变的问题

[复制链接]
发表于 2016-2-29 21:21:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
请大家帮帮我

a = [10,3]
def xx(a):
    a.append(5)
    return a
b = xx(a)
print(a)
print(b)

输出结果为:a:[10, 3, 5]      b: [10, 3, 5]      这里 a 在出函数之后也被改变了

a = 10
def xx(a):
    a=5
    return a
b = xx(a)
print(a)
print(b)

输出结果为:a:10      b:  5      这里 a 在出函数之后没有被改变

请问为什么会不一样呢?

谢谢大家
最佳答案
2016-2-29 22:25:28
本帖最后由 小小大鱼 于 2016-2-29 22:36 编辑

关键列表的修改方法,与变量的修改方法不同
  1. # 修改下第一个函数的形式
  2. a = [10,3]
  3. def xx(a):
  4.     a = [10,3,5]    #  等价a.append(5)
  5.     return a
  6. b = xx(a)
  7. print(a)
  8. print(b)
复制代码


从形式上,第一种形式与第二种形式一样。
第二种情况中,a没变的原因是:函数内变量a生命周期被限制在函数内,出了函数无效
说到修改的方式:
# python中变量都是引用
  1. a = 10  # a指向10,简单点说就是a是个标签,10是一个箱子,里面放了10块钱,a贴在箱子上,但出了函数,标签会被回收
  2. def xx(a):
  3.     a = 5   # 在函数内部生命周期内, 会在另一块内存创建一个变量a指向5,但这块内存出了函数会被回收
  4.     return a
  5. b = xx(a) #b引用了函数内部的a的值5
  6. print(a) #此时只剩下开始时的变量a 指向10
  7. print(b)
复制代码


但是列表 [10,3]的修改方式不一样,它不会另外创建一个a列表,并将其内容改成[10,3,5],而是直接在a列表的[10,3]基础上直接改,即将箱子里面的钱改了[10,3,5],再把标签贴上去

2是给你2个标签,给你2个箱子,其中一个标签和5块钱只给你看看,就收回去了,1是给你一个标签,但给了1个箱子,并向箱子里面加了5块钱

#为了说明这两种不同的修改方式,下面看下,修改前后变量的内存地址:
  1. >>> a = [1,2] # a为列表,修改前后,内存地址没变,即在原地修改
  2. >>> id(a)
  3. 1154044707848
  4. >>> a.append(3)
  5. >>> a
  6. [1, 2, 3]
  7. >>> id(a)
  8. 1154044707848
  9. >>> b =10 #b修改前后内存地址改变了
  10. >>> id(b)
  11. 1421922320
  12. >>> b = 5
  13. >>> id(b)
  14. 1421922160
  15. >>>
复制代码


写完感觉快把自己搞晕了,也不知道讲明白没有
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-2-29 22:06:14 | 显示全部楼层
因为append是引用传参, 你看看这个例子
  1. >>> a = [10, 3]
  2. >>> def xx(a):
  3.         a = [123]
  4.         return a

  5. >>> b = xx(a)
  6. >>> print(a)
  7. [10, 3]
  8. >>> print(b)
  9. [123]
  10. >>>
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-29 22:25:28 | 显示全部楼层    本楼为最佳答案   
本帖最后由 小小大鱼 于 2016-2-29 22:36 编辑

关键列表的修改方法,与变量的修改方法不同
  1. # 修改下第一个函数的形式
  2. a = [10,3]
  3. def xx(a):
  4.     a = [10,3,5]    #  等价a.append(5)
  5.     return a
  6. b = xx(a)
  7. print(a)
  8. print(b)
复制代码


从形式上,第一种形式与第二种形式一样。
第二种情况中,a没变的原因是:函数内变量a生命周期被限制在函数内,出了函数无效
说到修改的方式:
# python中变量都是引用
  1. a = 10  # a指向10,简单点说就是a是个标签,10是一个箱子,里面放了10块钱,a贴在箱子上,但出了函数,标签会被回收
  2. def xx(a):
  3.     a = 5   # 在函数内部生命周期内, 会在另一块内存创建一个变量a指向5,但这块内存出了函数会被回收
  4.     return a
  5. b = xx(a) #b引用了函数内部的a的值5
  6. print(a) #此时只剩下开始时的变量a 指向10
  7. print(b)
复制代码


但是列表 [10,3]的修改方式不一样,它不会另外创建一个a列表,并将其内容改成[10,3,5],而是直接在a列表的[10,3]基础上直接改,即将箱子里面的钱改了[10,3,5],再把标签贴上去

2是给你2个标签,给你2个箱子,其中一个标签和5块钱只给你看看,就收回去了,1是给你一个标签,但给了1个箱子,并向箱子里面加了5块钱

#为了说明这两种不同的修改方式,下面看下,修改前后变量的内存地址:
  1. >>> a = [1,2] # a为列表,修改前后,内存地址没变,即在原地修改
  2. >>> id(a)
  3. 1154044707848
  4. >>> a.append(3)
  5. >>> a
  6. [1, 2, 3]
  7. >>> id(a)
  8. 1154044707848
  9. >>> b =10 #b修改前后内存地址改变了
  10. >>> id(b)
  11. 1421922320
  12. >>> b = 5
  13. >>> id(b)
  14. 1421922160
  15. >>>
复制代码


写完感觉快把自己搞晕了,也不知道讲明白没有

评分

参与人数 2荣誉 +4 鱼币 +6 收起 理由
wangguohui + 1 + 1 支持楼主!
~风介~ + 3 + 5 支持楼主!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-1 09:14:51 | 显示全部楼层
简单理解一下,列表等可变类型如果在主程序定义,在函数中使用相当于全局变量,这里仅指函数中不改变地址的操作,如append,pop等。如果是重新赋值就与你程序2的整型变量一样了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-4 14:46:20 | 显示全部楼层
小小大鱼 发表于 2016-2-29 22:25
关键列表的修改方法,与变量的修改方法不同

详细
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-7 15:09:23 | 显示全部楼层
又来看一遍,每次看都有那么一点小收获
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 17:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表