免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3184 | 回复: 8
打印 上一主题 下一主题

请教一个python函数的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-05-13 18:07 |只看该作者 |倒序浏览

今天再csdn上看到一个函数:
  1. >>> def foo(bar=[]):        # bar is optional and defaults to [] if not specified
  2. ...    bar.append("baz")    # but this line could be problematic, as we'll see...
  3. ...    return bar
复制代码
执行结果是这样的:
  1. >>> foo()
  2. ["baz"]
  3. >>> foo()
  4. ["baz", "baz"]
  5. >>> foo()
  6. ["baz", "baz", "baz"]
复制代码
请教,为什么?

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
2 [报告]
发表于 2014-05-13 18:36 |只看该作者
execute one time , append() one 'bar', what's the problem?
everything is object.

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
3 [报告]
发表于 2014-05-13 18:47 |只看该作者
回复 2# qianguozheng


   还是没懂. bar 默认不是空列表参数么. 为嘛第二次会叠加?  ....

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
4 [报告]
发表于 2014-05-13 19:26 |只看该作者
古老的特性,小心使用就是优化技巧,不小心就是BUG。default参数在函数定义时就确定了,而且与函数定义同在,除非想用default参数做cache(list/set/dict),否则default最好是Immutable(int/str/bytes/tuple....)。

论坛徽章:
5
巨蟹座
日期:2014-08-28 18:12:342015年迎新春徽章
日期:2015-03-04 10:01:4415-16赛季CBA联赛之江苏
日期:2016-04-28 09:43:3115-16赛季CBA联赛之吉林
日期:2016-06-22 10:34:4315-16赛季CBA联赛之山西
日期:2016-08-16 16:29:55
5 [报告]
发表于 2014-05-14 17:18 |只看该作者
这个东西 有时 还真会让人困惑呢。baz=[] 中[] 是一个object 从函数开始 那就指向了这个object, 执行后append 再次调用foo 在函数内部baz 已映射好 所以每次都会append 你可以在return 之前print id(baz) 看下 每次调用都是同一个

论坛徽章:
0
6 [报告]
发表于 2014-05-15 09:28 |只看该作者
python函数参数分传值和传引用, 例如int, string, tuple型作为参数则为值传递,而 list, object, dict则为传引用,当以[ ]作为默认参数传递时在函数内部局部作用域内就引用了[]指向的地址,而每次append后是往同一个地址追加元素,故返回地址为同一内存地址。
改正:
    >>> def foo(bar=None):        # bar is optional and defaults to [] if not specified
    ...    if bar == None:
               bar = []                    #这样每次在内存中新构造一个[],返回不同的地址指向的list.
    ...    bar.append("baz")    # but this line could be problematic, as we'll see...
    ...    return bar

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
7 [报告]
发表于 2014-05-15 12:00 |只看该作者
楼上不准确吧?应该都是传引用的,只是有些是immutable有些是mutable

论坛徽章:
0
8 [报告]
发表于 2014-05-15 16:07 |只看该作者

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
9 [报告]
发表于 2014-05-15 16:55 |只看该作者
回复 8# a-plus
写的很好。这个特性像一个大坑,比较隐晦,还是显式设置更Pythonic。


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

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP