zoukankan      html  css  js  c++  java
  • python函数把可变数据类型当默认参数值的问题(转)

    add by zhj: 文章写的很好,其实只要默认参数在函数中只读不写,那默认值就不会被修改,可变类型做默认参数就不会有问题

    方法二中,当result is None时,修改result的指向,不再指向默认参数对象,而是赋值一个新的对象。如下,可以看到,result的id变化了

    In [4]: def f(p=None, q=[]):
       ...:     print id(p), id(q)
       ...:     if p is None:
       ...:         p = []
       ...:         print id(p)
       ...:         
    
    In [5]: f()
    9568656 140309648126608
    140309648094632
    
    In [6]: f()
    9568656 140309648126608
    140309648074944

    原文:https://blog.csdn.net/sinat_38068807/article/details/85677419

    说明:默认参数值在函数被定义时已经计算出来,而不是在程序运行时。Python 程

    序员经常犯的一个错误是把可变的数据类型(例如列表或者字典)当作默认参数值

    (一)出现的问题

    在下面的例子中,函数 buggy() 在每次调用时,添加参数 arg 到一个空的列表 result ,然
    后打印输出一个单值列表。但是存在一个问题:只有在第一次调用时列表是空的,第二次
    调用时就会存在之前调用的返回值

    def buggy(arg, result=[]):
        result.append(arg)
        print(result)
    
    print('--------1--------')
    buggy('a')
    print('--------2--------')
    buggy('b')  # 期望得到 ['b']

    执行结果:

    --------1--------
    ['a']
    --------2--------
    ['a', 'b']

    (二)解释并测试

    1.默认参数值在函数被定义时已经计算出来,而不是在程序运行时

    2.只要函数调用时没有传递新的列表来覆盖默认参数列表,函数就会使用定义时的那个列表,并且操作依次叠加

    3.上面两次调用中,都没有传递新的列表,程序会调用定义函数时保存的默认参数,并在上一次的基础上进行操作叠加,即:列表在append的时候会在 result原来的基础上append追加值,所以会产生以上结果.

    我们通过打印列表的ID进行辨识来看看:

    def buggy(arg, result=[]):
        print(id(result))
        result.append(arg)
        print(result)
    
    print('--------1--------')
    buggy('a')
    print('--------2--------')
    buggy('b')  # expect ['b']

    结果:

    --------1--------
    12205768
    ['a']
    --------2--------
    12205768
    ['a', 'b']

    我们会发现ID值是相同的;

    说明两次执行时使用的都是开始定义函数时的默认参数 ,进行了操作叠加

    4.下面我们传递新的列表看看:

    def buggy(arg, result=[]):
        print(id(result))
        result.append(arg)
        print(result)
    
    print('--------1--------')
    buggy('a')
    print('--------2--------')
    buggy('b', [])  # 传递了新的列表

    结果:

    --------1--------
    18497224
    ['a']
    --------2--------
    18504648
    ['b']

    发现,列表id不同,并且得到了我们期望的值

    (三)解决方法

    方法1

    # 如果写成下面的样子就会解决刚才的问题:
    
    def works(arg):
        result = []
        result.append(arg)
        print(result)
    
    works('a')
    works('b')

    结果:

    ['a']
    ['b']

    方法2:

    # 这样的修改也为了表明是第一次调用跳过一些操作:
    
    def nonbuggy(arg, result=None):
        if result is None:
            result = []
        result.append(arg)
        print(result)
    
    nonbuggy('a')
    nonbuggy('b')

    结果:

    ['a']
    ['b']
  • 相关阅读:
    1、远程连接工具
    Restful架构API编码规范
    61、springmvc-异步请求-返回DeferredResult
    60、springmvc-异步请求-返回Callable
    59、servlet3.0-异步请求
    58、springmvc-定制与接管SpringMVC
    HTTP层 —— 响应
    HTTP层 —— 请求
    HTTP层 —— 控制器
    HTTP层 —— CSRF保护
  • 原文地址:https://www.cnblogs.com/ajianbeyourself/p/10739283.html
Copyright © 2011-2022 走看看