[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 ...
随机推荐
- python 爬虫 ~ 查看收发包的情况
DebugLog 可以用来查看收发包的情况,比较有意思,现特意记录下来: Sample: import urllib2 httpHandler = urllib2.HTTPHandler(debugl ...
- HDU 6096 String (AC自动机)
题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...
- URAL 1416 Confidential (最小生成树+次小生成树)
Description Zaphod Beeblebrox - President of the Imperial Galactic Government. And by chance he is a ...
- php 获取唯一字符串与文件扩展名函数
/** * 生成唯一字符串 * @return string */ function getUniqueStr(){ return md5(uniqid(microtime(true),true)); ...
- glut glew区别
GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口.使用OpenGL的朋友都知道,window目前只支持OpenGL1.1的涵数,但 OpenGL现在都发展到2.0以上了,要使用这些Open ...
- 对于Json的认识
Json简介 1. JSON 是什么 JSON,全称是 JavaScript Object Notation,即 JavaScript 对象标记法. JSON 是一种轻量级(Light-Weigh ...
- 20165227 实验三《敏捷开发与XP实践》实验报告
2017-2018-4 20165227 实验三<敏捷开发与XP实践>实验报告 实验内容 1.XP基础 2.XP核心实践 3.相关工具 实验要求 1.没有Linux基础的同学建议先学习&l ...
- MeasureSpec介绍及使用详解
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求.一个MeasureSpec有大小和模式组成.他有三种模式: UNSPECIFIED ...
- C++ 和 MFC的学习
1. 在Windows应用程序设计中,既可以使用个C的基本数据类型,也可以使用Windows自定义的数据类型.但要注意,凡是Windows自定义的关键字都要大写. 2. 什么是句柄? 在Windows ...
- linux arm的存储分布那些事之一【转】
转自:http://blog.csdn.net/xiaojsj111/article/details/11724081 linux arm的存储分布那些事之一 linux arm 内存分布总览 上图是 ...