首页 > 代码库 > python 在调用时计算默认值
python 在调用时计算默认值
大家都知道python的默认值是在函数定义时计算出来的, 也就是说默认值只会计算一次, 之后函数调用时, 如果参数没有给出,
同一个值会赋值给变量, 这会导致, 如果我们想要一个list默认值, 新手通常这么写:
def foo(a=[]): a.append(3) print a
其实是错误的,两次调用会这样的结果:
[3][3, 3]
其实应该这么写
def baz(a=None):
a = a or [] a.append(3) print a
两次调用输出以下结果:
[3][3]
这样好挫啊, 搞的虽然有默认值用法,但是我们却需要写的和js,lua一样, 我们不能像c++一样, 在函数运行时每次执行默认值么.
用decorator可以模拟下
import functools
import copy
def compute_default_value_for_each_call(func): defaults = func.__defaults__ if not defaults: return None defaults = tuple(copy.copy(x) for x in defaults) @functools.wraps(func) def wrapper(*args, **kwargs): if func.__defaults__ != defaults: func.__defaults__ = tuple(copy.copy(y) for y in defaults) return func(*args, **kwargs) return wrapper@compute_default_value_for_each_calldef foo(b, a=[]): if b: a.append(3) return aimport timeit
这样两次调用foo(1), 结果为:
[3][3]
这个decorator有对未修改默认参数值做优化, 在我们不对默认值修改的情况下(比如打印变量a的内容), 性能有很大提升:
@compute_default_value_for_each_calldef foo(b, a=[]): if b: a.append(3) return adef foo2(b, a=None): a = a or [] if b: a.append(3) return aimport timeitprint timeit.timeit(‘foo(1)‘, setup=‘from __main__ import foo‘)print timeit.timeit(‘foo(0)‘, setup=‘from __main__ import foo‘)print timeit.timeit(‘foo2(1)‘, setup=‘from __main__ import foo2‘)print timeit.timeit(‘foo2(0)‘, setup=‘from __main__ import foo2‘)
执行结果(调用1000000次的总时间)
4.327049970630.6301090717320.4458589553830.26370882988
性能上还过得去....
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。