一个老问题:

 def func(defau=[]):
defau.append(1)
return defau print(func())#print[1]
print(func())#print[1,1]
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:

 def func(defau=[]):
defau.append(1)
return defau print(id(func()))#print 1756350390856
print(id(func()))#print 1756350390856
print(id(func()))#print 1756350390856

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

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

 import timeit
setup1="""
import math
def cal():
math.sin(1)+math.cos(1)
"""
setup2="""
import math
def cal2(sin=math.sin,cos=math.cos):
sin(1)+cos(1)
"""
t1=timeit.Timer(setup1,"print('setup1')")
t2=timeit.Timer(setup2,"print('setup2')")
print(t1.timeit(100))
print(t2.timeit(100))
#setup1
#0.0003371067712671346
#setup2
#8.921092541729796e-05

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

参考资料:[1]python 文档

     [2]Default parameter values in python

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

[python]一个关于默认参数的老问题和一个有关优化的新问题的更多相关文章

  1. Python中的默认参数(转)

    add by zhj: Python设计者为何将默认参数设计成这样呢?参见Python函数参数默认值的陷阱和原理深究 原文:https://github.com/acmerfight/insight_ ...

  2. Python进阶-函数默认参数

    Python进阶-函数默认参数 写在前面 如非特别说明,下文均基于Python3 一.默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 ...

  3. python中的默认参数

    https://eastlakeside.gitbooks.io/interpy-zh/content/Mutation/ 看下面的代码 def add_to(num, target=[]): tar ...

  4. C/C++ Python的函数默认参数

    发现C/C++  Python的函数可以使用默认参数,来减少传参时候的参数个数. 但是:这样的默认参数最好是不变对象! #include <stdio.h> #include <st ...

  5. Python函数的默认参数的设计【原创】

    在Python教程里,针对默认参数,给了一个“重要警告”的例子: def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print( ...

  6. 在python函数中默认参数的一些坑

    一.默认参数 python为了简化函数的调用,提供了默认参数机制: 这样在调用pow函数时,就可以省略最后一个参数不写: 在定义有默认参数的函数时,需要注意以下: 必选参数必须在前面,默认参数在后: ...

  7. Python之定义默认参数

    定义函数的时候,还可以有默认参数. 例如Python自带的 int() 函数,其实就有两个参数,我们既可以传一个参数,又可以传两个参数: >>> int('123') 123 > ...

  8. python里的默认参数

    def extendList(val, test=[]): test.append(val) return test list1 = extendList(10) list2 = extendList ...

  9. 经典面试题-python函数之默认参数

    1.可变的默认参数----list  示例: def add(a, mylist=[]): # print(id(mylist)) mylist.append(a) return mylist pri ...

随机推荐

  1. bzoj 2456: mode ——独特水法

    Description 给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数. Input 第1行一个正整数n.第2行n个正整数用空格隔开. Output 一行一个正整数表 ...

  2. jquery $.post() 向php传值 实现简单的二级联动

    更多内容推荐微信公众号,欢迎关注: 1 其中selectid是一个下拉菜单的id $().ready(function () { $("#selectid").change(fun ...

  3. 在JS数组指定位置插入元素

    很多与数组有关的任务听起来很简单,但实际情况并不总是如此,而开发人员在很多时候也用不到他.最近我碰到了这样一个需求: 将一个元素插入到现有数组的特定索引处.听起来很容易和常见,但需要一点时间来研究它. ...

  4. 洛谷 P4093: bzoj 4553: [HEOI2016/TJOI2016]序列

    题目传送门:洛谷P4093. 题意简述: 给定一个长度为 \(n\) 的序列 \(a\). 同时这个序列还可能发生变化,每一种变化 \((x_i,y_i)\) 对应着 \(a_{x_i}\) 可能变成 ...

  5. 【比赛游记】THUSC2018酱油记

    day -1 早上4:30就要起来去飞机场…… 7点的飞机,10:30就到北京了. 北京的街景并没有我想像的漂亮……大概是因为我在四环外〒▽〒 晚上还有CF div3场,果断的去水了,因为太累就没有打 ...

  6. sleep允许休眠, delay不允许

    在Linux Driver开发中,经常要用到延迟函数:msleep,mdelay/udelay. 虽然msleep和mdelay都有延迟的作用,但他们是有区别的. 1.)对于模块本身 mdelay是忙 ...

  7. 03.JavaScript简单介绍

    一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) N ...

  8. openstack发展历程及其架构简介

    1.0 Openstack介绍 OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其宗旨在于,帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云,也 ...

  9. Android页面之间进行数据回传

    要求:页面1跳转到页面2,页面2再返回页面1同时返回数据 页面1添加如下代码: Intent intent = new Intent(); intent.setClass(页面1.this, 页面2. ...

  10. MongoDB中多表关联查询(

    1.使用aggregate 查看表数据 db.getCollection('reports').aggregate([ { $lookup: { from: "process", ...