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 functoolsimport copydef 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_call
def foo(b, a=[]):
    if b:
        a.append(3)
    return a

import timeit

这样两次调用foo(1), 结果为:

[3]
[3]

这个decorator有对未修改默认参数值做优化, 在我们不对默认值修改的情况下(比如打印变量a的内容), 性能有很大提升:

@compute_default_value_for_each_call
def foo(b, a=[]):
    if b:
        a.append(3)
    return a

def foo2(b, a=None):
    a = a or []
    if b:
        a.append(3)
    return a

import timeit

print 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.32704997063
0.630109071732
0.445858955383
0.26370882988

性能上还过得去....

python 在调用时计算默认值

时间: 2024-10-18 12:29:53

python 在调用时计算默认值的相关文章

.NET DateTime类型变量作为参数时设置默认值

一个小的 Tips. .NET 中函数参数的默认值需要是编译时常量.如果参数是引用类型,可以设置Null,如果是值类型,可以设置相应的编译时常量,如整型可以用整数,但对于DateTime(结构体,值类型)想要设置默认类型时要如何处理? 通常情况下会给 DateTime 结构体默认当时时间,即 DateTime.Now,但 DateTime.Now 不是编译时常量,因此无法通过编译. 如以下代码无法通过编译: public const DateTime defaultDateTime = Date

001. 为input type=text 时设置默认值

1. 前端HTML代码 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> 2 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3

Python两种方法计算MD5值

1.Python内置md5模块 1 #-*- coding:utf-8 -*- 2 3 import md5 4 5 def Str2Md5(s): 6 m=md5.new() 7 m.update(s) 8 return m.hexdigest() 9 10 if __name__=="__main__": 11 s="www.baidu.com" 12 print Str2Md5(s) 2.Python的hashlib模块 1 #-*- coding:utf-8

Python模块调用时的路径查找

import sys import os base_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(base_dir) os.path.abspath(__file__) 确认*.py的绝对路径 os.path.dirname(os.path.abspath(__file__)) 返回*.py的上一级文件路径 sys.path.append(base_dir) 添加搜索路径  

input 默认值为灰色,输入时清楚默认值

<input value="please input your name" onFocus="if(value==defaultValue){value='';this.style.color='#000'}" onBlur="if(!value){value=defaultValue; this.style.color='#999'}" style="color:#999" ng-model="owner_n

清除网站设计时的默认值

/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, in

ES6---函数的扩展之函数的默认值

1.函数默认值 function add(a,b=3){ return a+b; } add(1,2);//3 add(1);//4 理解起来也很简单,就是在函数定义的时候设置一个默认值,当调用函数没有传参时,可以根据默认值为其匹配一个参数值 这样子的好处嘛,可以避免在调用时没有传参导致函数报错,同时对于阅读代码也更加直观了,代码量也更少了,嘻嘻 直观是因为我们只需要看函数就知道该参数是否可选 代码更少是因为在ES6以前,函数不能设置默认值,如果在调用的时候没有传参进去, 那么需要进行是否传递该

研究下JavaScript中的Rest参数和参数默认值

研究下JavaScript中的Rest参数和参数默认值 本文将讨论使 JavaScript 函数更有表现力的两个特性:Rest 参数和参数默认值. Rest 参数 通常,我们需要创建一个可变参数的函数,可变参数是指函数可以接受任意数量的参数.例如,String.prototype.concat 可以接受任何数量的字符串作为参数.使用 Rest 参数,ES6 为我们提供一种新的方式来创建可变参数的函数. 我们来实现一个示例函数 containsAll,用于检查一个字符串中是否包含某些子字符串.例如

ES6笔记之参数默认值(译)

原文链接:http://dmitrysoshnikov.com/ 原文作者:Dmitry Soshnikov 译者做了少量补充.这样的的文字是译者加的,可以选择忽略. 在这个简短的笔记中我们聊一聊ES6的又一特性:带默认值的函数参数.正如我们即将看到的,有些较为微妙的CASE. ES5及以下手动处理默认值 在ES6默认值特性出现前,手动处理默认值有几种方式: function log(message, level) { level = level || 'warning'; console.lo