默认参数注意点

优点:灵活,当没有指定与形参对应的实参时就会使用默认参数

缺陷:

例子:

>>> def h(m, l=[]):                    #默认参数时列表,可变对象

... l.append(m)

... print id(l)

... return l

...

>>> h(1)

140373466854392

[1]

>>> h(2)

140373466854392                    #在多次调用的过程中l的id并没有变换

[1, 2]                                #意外的结果[1,2]

关于默认参数,文档中是这样说的:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same "pre-computed" value is used for each call.

大概意思:但解释器执行函数定义时,默认参数值也被计算了,这也意味着默认参数里的表达式只是被执行了一次,而且每次调用都是用同样的上面预先计算的值

  所以上面的例子就很容易理解,list在函数定义的时候,就被定义好了,函数的多次调用,都在用一个list

怎么理解

实际上,函数就是一个对象;当python执行def语句时,它会根据编译好的函数体字节码和命名空间等信息新建这个对象,并且会计算默认参数的值。函数的所有构成要素均可通过它的属性来访问,比如可以用func_name属性来查看函数的名称。所有默认参数值则存储在函数对象的__defaults__属性中,它的值为一个列表,列表中每一个元素均为一个默认参数的值

>>> dir(h)

['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

>>> h.__defaults__

([1, 2],)

>>> h(3)

140373466854392

[1, 2, 3]

>>> h.__defaults__

([1, 2, 3],)

解决办法:动态生成对象,在定义的时候使用None对象做占位符;

前面的例子可以改写成:

>>> def h(a,l=None):

... if l is None:

... l=[]

... l.append(a)

... print id(l)

... return l

...

>>> h(1)

140373466854392

[1]

>>> h(2)

140373466843904

[2]

>>> h(2,[1,2])

140373466854392

[1, 2, 2]

再一个例子:实时返回系统

>>> def t1(when = time.time()):    #默认参数在函数定义的时候就被执

... time.sleep(1)                            行了,且多次调用都在使用同一个

... return when

>>> def t2(when = time.time):                #默认参数只是对象

... time.sleep(1)

... return when

>>> a1=t1()

1448022680.552696

>>> a2=t2()

<built-in function time>

>>> a2()

1448022764.78878

>>> a2()

1448022767.4640501

1448022790.4568429

变长参数

使用方法:

*args 表示任何多个无名参数,它被封装在一个tuple

>>> def f(*a):

... return sum(a)

...

>>> f(1,2,3)

6

**kwargs表示关键字参数,它被封装一个dict

>>> def b(**kw):

... for i,v in kw.items():

... print 'key={0}, value={1}'.format(i,v)

...

>>> b(n=2, name='wxl')

key=name, value=wxl

key=n, value=2

args和kwargs可以随意命名。*args 要在**kwargs前面使用,否则语法错误

适合变长参数场景:

  1. 修饰器中的使用:比如在django中使用@login_req来规定用户必须在登录状态下才能使用该函数,而修饰函数有很多,参数不同,所以变长函数很好解决问题

    def login_req(main):

    def required(request,*args,**kwargs):

    if not request.session.get('is_login', None):

    return redirect('/login/')

    else:

    return main(request,*args,**kwargs)

    return required

    @login_req

    def index(request):

    return render_to_response("index.html")

  2. 参数的数目不确定,如读取配置文件test.cfg、做全局变量等:

    >>> from ConfigParser import ConfigParser

    >>> conf= ConfigParser()

    >>> conf.read('test.cfg')

    ['test.cfg']

    >>> conf.items('params')

    [('name', 'wxl'), ('age', '21'), ('height', '180')]

    >>> dict(conf.items('params'))

    {'age': '21', 'name': 'wxl', 'height': '180'}

  3. 当子类调用父类的某些方法,这种如果改变父类程序时,子程序可以不改动

    >>> class Super( object ):

    ... def __init__( self, this, that ):

    ... self.this = this

    ... self.that = that

    ...

    >>> class Sub( Super ):

    ... def __init__( self, myStuff, *args, **kw ):

    ... super( Sub, self ).__init__( *args, **kw )

    ... self.myStuff= myStuff

函数传参既不是传值也不是传引用,而是传对象

与c语言不同的是,python赋值的方式是引用

>>> a=5;

  >>> b=a

>>> id(a)

35365592

>>> id(b)

35365592

>>> b=7

>>> id(b)

35365544

上面赋值a的操作实际上是将a指向5所在的内存地址

b=a     b相当与a的别名,同样也指向5所在的内存地址

b=7 相当于申请了一块存放有7的内存空间,再把b指向7所在的内存空间

所以python函数中,函数参数在传递的过程中是将整个对象传入,对于可变对象的修改在函数外部及函数内部都可见,调用函数和被调函数之间共享这个对象,

而对于不可变对象,由于并不能真正地被修改,因此,修改通常通过新建对象然后赋值指向来实现

python中函数参数的更多相关文章

  1. (转)python中函数参数中如果带有默认参数list的特殊情况

    在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 1 2 3 4 5 6 7 8 9 def f(x,l=[]):     for i in range(x):         ...

  2. python中函数参数的引用方式

    值传递和引用传递时C++中的概念,在python中函数参数的传递是变量指向的对象的物理内存地址!!! python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方 ...

  3. 对Python中函数参数类型及排序问题,三个方面的总结

    Python中函数的参数问题有点复杂,主要是因为参数类型问题导致的情况比较多,下面来分析一下. 参数类型:缺省参数,关键字参数,不定长位置参数,不定长关键字参数. 其实总共可以分为 位置参数和关键字参 ...

  4. python中函数参数*args和**kw的区别

    1.函数与参数(实参) 在python中创建函数是def,创建函数名是def f(),f函数名字,def f(a,b),这里的a,b是两个参数,函数名是自定义的,参数也是自定义,随意就好.看图如下效果 ...

  5. Python中函数参数类型和参数绑定

    参数类型 Python函数的参数类型一共有五种,分别是: POSITIONAL_OR_KEYWORD(位置参数或关键字参数) VAR_POSITIONAL(可变参数) KEYWORD_ONLY(关键字 ...

  6. Python中函数参数 *args 和 **kwargs

    普通参数,即在调用函数时必须按照准确的顺序来进行参数传递. 默认参数,即参数含有默认值,在调用函数时可以进行参数传递,若没有进行参数传递则使用默认值,要注意,默认参数必须在普通参数的右侧(否则解释器无 ...

  7. python中函数的参数

    函数参数(一) 思考一个问题,如下: 现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗? def add2num(): a = 1 ...

  8. python 中函数参数传递形式

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  9. python中函数参数传递的几种方法

    转自  http://www.douban.com/note/13413855/ Python中函数参数的传递是通过“赋值”来传递的.但这条规则只回答了函数参数传递的“战略问题”,并没有回答“战术问题 ...

随机推荐

  1. delphi 中OutputDebugString 函数的妙用(使用DebugView或者Pascal Analyzer软件,在运行过程中就能监视和捕捉日志,而且通过网络就能监视)

    原文地址 https://www.peganza.com/delphi-and-outputdebugstring.html 曾经想要实时监控您的Delphi应用程序,并能够查看日志消息吗?当然,您始 ...

  2. poj 1180 Batch Scheduling (斜率优化)

    Batch Scheduling \(solution:\) 这应该是斜率优化中最经典的一道题目,虽然之前已经写过一道 \(catstransport\) 的题解了,但还是来回顾一下吧,这道题其实较那 ...

  3. HBase运维和优化

    管理工具 HBase ShellHBase Shell是HBase组件提供的基于JRuby IRB的字符界面的交互式客户端程序,通过HBase Shell可以实现对HBase的绝大部分操作 通过hel ...

  4. Java 深拷贝浅拷贝 与 序列化

    一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会 ...

  5. 大O符号

    大O 就是 时间复杂度.时间复杂度是大概的描述一个算法的用时(实际上从侧面的表达了他的效率) 最好时间复杂度,通常指在最好情形下,这个算法用时.反之,最坏情况下的就是最坏时间复杂度.通常 冒泡算法 的 ...

  6. Simple JavaScript Inheritance

    1. [代码]Simple JavaScript Inheritance     (function(){  var initializing = false, fnTest = /xyz/.test ...

  7. cassandra解析-log写

    db/Keyspace.java 中的 apply 函数 中的 commitLogPosition = CommitLog.instance.add(mutation); 这一句确认是写log的代码. ...

  8. hdu-5720 Wool(区间并+扫描线)

    题目链接: Wool Time Limit: 8000/4000 MS (Java/Others)     Memory Limit: 262144/262144 K (Java/Others) Pr ...

  9. Objective-C基础知识

    内联函数 “内联函数”是一个很老的概念,在其他语言譬如C++语言中也出现了.所谓“内联函数”指的是“有函数的结构,但不具备函数的性质,类似于宏替换功能的代码块”. 在实际应用中,常常把规模较小.逻辑较 ...

  10. 深入理解dispatch_sync

    关于GCD的基础知识,之前写过一篇博客,详见GCD基础知识.虽然之前已经梳理过了,但对很多知识点的理解仍然不够透彻…写这篇博客的原因是在阅读AFNetworking代码时遇到一些奇怪的代码. 如下: ...