V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
dddd
V2EX  ›  Python

请赐教,完全搞不清啊!因为列表不可变??列表的作用域不同??好想 代码如下:

  •  
  •   dddd · 2014-06-22 18:00:06 +08:00 · 3036 次点击
    这是一个创建于 3805 天前的主题,其中的信息可能已经有所发展或是发生改变。
    # [1] 累积
    >>> def f(a, L=[]):
    ... L.append(a)
    ... return L
    ...
    >>> print(f(1))
    [1]
    >>> print(f(2))
    [1, 2]
    # [2] 不累积
    >>> def f(a, L=None):
    ... if L is None:
    ... L = []
    ... L.append(a)
    ... return L
    ...
    >>> print(f(1))
    [1]
    >>> print(f(3))
    [3]
    # [3] 调换矩阵行和列
    >>> matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
    >>> a = []
    >>> for i in range(4):
    ... a_row = []
    ... for row in matrix:
    ... a_row.append(row[i])
    ... a.append(a_row)
    ...
    >>> a
    [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

    问题:  [3] 中列表 a_row 不累积??是因为列表的作用域吗??那上面的 [1] 累积的列表又是什么情况??不是每次调用都赋值为[]吗??还是应为列表是不可变的,混乱了,根本不知道自己在想什么,求大神给我脑袋一砖……
    9 条回复    2014-06-23 13:21:30 +08:00
    tonychow
        1
    tonychow  
       2014-06-22 18:06:19 +08:00   ❤️ 1
    这是 Python?Python 中的列表是可变的,这个问题参考: http://blog.jobbole.com/68256/
    hitsmaxft
        2
    hitsmaxft  
       2014-06-22 18:38:15 +08:00   ❤️ 2
    说明python的默认参数值并不是每次调用都重新生成的,为了提高效率, 在函数初始化时只生成一个实例。

    这么做可以硬生生带来一堆的麻烦。。

    所以最好别把默认参数作为处理对象, 而是自己手动构建一个新实例。

    像这种就非常不安全

    def holyshit(a1, a2=[]):
    >>>>a2.ppend(a1)
    >>>>return a2

    a = holyshit(1); a.apend(1);

    下一个调用的人就傻了。

    所以最佳实践是,

    只使用依赖默认参数影响流程, 而不是操作它。

    def safeFunc(input, isSomething=True);

    或者

    def getSome(key, defaultValue=None);
    hitsmaxft
        3
    hitsmaxft  
       2014-06-22 18:38:45 +08:00
    说明python的默认参数值并不是每次调用都重新生成的,为了提高效率, 在函数初始化时只生成一个实例。

    这么做可以硬生生带来一堆的麻烦。。

    所以最好别把默认参数作为处理对象, 而是自己手动构建一个新实例。

    像这种就非常不安全

    def bad(a1, a2=[]):
    >>>>a2.append(a1)
    >>>>return a2

    a = bad(1); a.append(1);

    下一个调用的人就傻了。

    所以最佳实践是,

    只使用依赖默认参数影响流程, 而不是操作它。

    def safeFunc(input, isSomething=True);

    或者

    def getSome(key, defaultValue=None);
    ljcarsenal
        4
    ljcarsenal  
       2014-06-22 18:48:22 +08:00 via Android
    搞不懂你在说什么。。。累积什么意思。第三个每次i循环的时候a_row不都是清空么。第一个的话我也是第一次见这么用
    ljcarsenal
        5
    ljcarsenal  
       2014-06-22 18:50:24 +08:00 via Android   ❤️ 1
    immutable的赋值会开辟新内存 mutable的不会  对于immutable如数字:a=1,b=a,c=1,则 id(a)==id(b)==id(c),一旦b改变如 b+=1,则id(b)!=id(a);
    对于mutable的如 list  aa=[1],bb=aa,cc=[1],则id(a)!=id(c),而id(a)永远==id(b),不管b怎么变 a跟着变
    dddd
        6
    dddd  
    OP
       2014-06-22 19:02:17 +08:00
    @tonychow 对,可变
    dddd
        7
    dddd  
    OP
       2014-06-22 19:58:58 +08:00
    @ljcarsenal 可变的(mutable)默认参数在每次函数调用时保持了它们的状态,它们能提供C语言中静态变量一样的功能。这样就清晰多了http://blog.jobbole.com/69834/
    manfay
        8
    manfay  
       2014-06-22 20:33:42 +08:00
    楼主,前两个例子说的是函数的问题,第三个不是函数,不能混为一谈啊。

    其中,第2个例子在每次调用函数时都会执行一次 L=[],所谓的不累积正是这个原因。
    jokester
        9
    jokester  
       2014-06-23 13:21:30 +08:00
    1中参数默认值是`[]`这个*值*, 而不是一个"每次调用时返回`[]`的*过程*"

    2也是 不过None是immutable的 每次得到同一个对象也不造成问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5262 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 79ms · UTC 08:20 · PVG 16:20 · LAX 00:20 · JFK 03:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.