zoukankan      html  css  js  c++  java
  • [python]一个关于默认参数的老问题和一个有关优化的新问题

    一个老问题:

    1 def func(defau=[]):
    2     defau.append(1)
    3     return defau
    4     
    5 print(func())#print[1]
    6 print(func())#print[1,1]
    7 print(func())#print[1,1,1]

    学python时候应该都遇到过这个问题,为什么?一般的说法是把这个可变的默认参数和函数绑定在一块了

    但是,怎么绑定的???

    python文档[1],里面对def的解释:

    A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object .

    一个可执行的声明,在现有的名称空间中把函数名字和函数对象绑定在一块了。

    也就是说,这种绑定只有在def声明执行的时候才会发生,只有在def语句执行的时候,才会把函数名字和一个新的函数对象绑定在一块[2]。

    那么,这些和默认参数有什么关系?

    这默认参数的关系就是,只有当这种绑定发生的时候,默认参数才会得到赋值,换句话说,只有在def声明执行的时候,默认参数所引用的对象才会和函数对象结合起来。

    所以,在上面的例子中,因为def语句只执行了一次,所以几次调用函数func其实都是执行的同一个函数对象,使用的同一个list:

    1 def func(defau=[]):
    2     defau.append(1)
    3     return defau
    4     
    5 print(id(func()))#print 1756350390856
    6 print(id(func()))#print 1756350390856
    7 print(id(func()))#print 1756350390856

    看大神laike9m的博客[3]的时候,发现其实可以利用这一点对python的性能进行优化的。

    我们都知道,python中名称的查找顺序为LEGB,也就是local->enclosing->global->builtin,如果我们把一个全局变量赋值给一个函数的默认参数,把一个全局变量变为一个函数的局部变量,那么在查找链中,就不用进行到global,直接在local域中就可以得到需要的变量了:

     1 import timeit
     2 setup1="""
     3 import math
     4 def cal():
     5     math.sin(1)+math.cos(1)
     6     """
     7 setup2="""
     8 import math
     9 def cal2(sin=math.sin,cos=math.cos):
    10     sin(1)+cos(1)
    11     """
    12 t1=timeit.Timer(setup1,"print('setup1')")
    13 t2=timeit.Timer(setup2,"print('setup2')")
    14 print(t1.timeit(100))
    15 print(t2.timeit(100))
    16 #setup1
    17 #0.0003371067712671346
    18 #setup2
    19 #8.921092541729796e-05

    可以看到,在执行100遍的情况下,运行时间相差一个量级

    参考资料:[1]python 文档

         [2]Default parameter values in python

                  [3]pythony优化函数执行的技巧

  • 相关阅读:
    postman的使用
    测试模型的发展论
    winform 控件没有Cursor属性时的处理办法
    【C#】两个DataTable关联查询(inner join、left join)C#代码
    【C#】datetimepicker里面如何设置日期为当天日期,而时间设为0:00或23:59?
    【C#】string格式的日期转为DateTime类型及时间格式化处理方法
    js解析后台传过来的json
    shell做成csv文件
    Hibernate查询总的记录数
    在引入的css或者js文件后面加参数的作用
  • 原文地址:https://www.cnblogs.com/fcyworld/p/6846354.html
Copyright © 2011-2022 走看看