[python]一个关于默认参数的老问题和一个有关优化的新问题
一个老问题:
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
[python]一个关于默认参数的老问题和一个有关优化的新问题的更多相关文章
- Python中的默认参数(转)
add by zhj: Python设计者为何将默认参数设计成这样呢?参见Python函数参数默认值的陷阱和原理深究 原文:https://github.com/acmerfight/insight_ ...
- Python进阶-函数默认参数
Python进阶-函数默认参数 写在前面 如非特别说明,下文均基于Python3 一.默认参数 python为了简化函数的调用,提供了默认参数机制: def pow(x, n = 2): r = 1 ...
- python中的默认参数
https://eastlakeside.gitbooks.io/interpy-zh/content/Mutation/ 看下面的代码 def add_to(num, target=[]): tar ...
- C/C++ Python的函数默认参数
发现C/C++ Python的函数可以使用默认参数,来减少传参时候的参数个数. 但是:这样的默认参数最好是不变对象! #include <stdio.h> #include <st ...
- Python函数的默认参数的设计【原创】
在Python教程里,针对默认参数,给了一个“重要警告”的例子: def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print( ...
- 在python函数中默认参数的一些坑
一.默认参数 python为了简化函数的调用,提供了默认参数机制: 这样在调用pow函数时,就可以省略最后一个参数不写: 在定义有默认参数的函数时,需要注意以下: 必选参数必须在前面,默认参数在后: ...
- Python之定义默认参数
定义函数的时候,还可以有默认参数. 例如Python自带的 int() 函数,其实就有两个参数,我们既可以传一个参数,又可以传两个参数: >>> int('123') 123 > ...
- python里的默认参数
def extendList(val, test=[]): test.append(val) return test list1 = extendList(10) list2 = extendList ...
- 经典面试题-python函数之默认参数
1.可变的默认参数----list 示例: def add(a, mylist=[]): # print(id(mylist)) mylist.append(a) return mylist pri ...
随机推荐
- POJ 2485 Highways( 最小生成树)
题目链接 Description The islandnation of Flatopia is perfectly flat. Unfortunately, Flatopia has no publ ...
- vue、入门
入门vue v-on:click:chang 绑定事件点击 生面周期,整个vue的执行过程,他的应用执行了生面周期,也就是执行过程,这个执行过程如下图表,我们可以参考下图,也可以访问官方网址:ht ...
- Hive笔记之数据库操作
创建数据库 hive创建数据库的最简单写法和mysql差不多: create database foo; 仅当名为foo的数据库当前不存在时才创建: create database if not ex ...
- ctime 时间
1. 类型clock_t: 是个long型,用来记录一段时间内的时钟计时单元数,即CPU的运行单元时间.size_t: 标准C库中定义的,应为unsigned int,在64位系统中为long uns ...
- opencv 摄像头
VideoCapture cap(); if(!cap.isOpened()) ; Mat frame, edges; namedWindow(); for(;;) { cap >> fr ...
- perl6: hash小笔记
> ,,, { => , => } > my $a = :%h h => { => , => } > $a.perl :h({, }) > my ...
- TCP检验和
TCP的检验和 检验和目的 目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动.如果接收方检测到检验和有差错,则TCP段会被直接丢弃. TCP在计算检验和时,要加上一个12字节的伪首 ...
- Linux USB驱动学习总结(二)---- USB设备驱动
USB 设备驱动: 一.USB 描述符:(存在于USB 的E2PROM里面) 1. 设备描述符:struct usb_device_descriptor 2. 配置描述符:struct usb_c ...
- httpd功能配置之虚拟主机【转】
apache默认使用80端口提供服务,使用主服务器配置的话,一台物理机只能提供一个站点服务:可以使用虚拟主机方式提供不同的访问,以实现一台主机提供多站点服务. 虚拟主机的实现方式有三种:基于端口.基于 ...
- html 列表标签
1.有序列表 <ol> <li>你好</li> <li>你好</li> <li>你好</li> </ol> ...