默认参数注意点

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

缺陷:

例子:

>>> 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. gRPC错误码 http状态码 provide your APIs in both gRPC and RESTful style at the same time

    How gRPC error codes map to HTTP status codes in the response https://github.com/grpc-ecosystem/grpc ...

  2. 关于谷歌浏览器默认字体12px的解决方案

    1. * Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示, 可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决. 超链接访问 ...

  3. Redis持久化(RDB和AOF)

    什么是Redis持久化 什么是Redis持久化,就是将内存数据保存到硬盘. Redis 持久化存储 (AOF 与 RDB 两种模式) RDB持久化 RDB 是以二进制文件,是在某个时间 点将数据写入一 ...

  4. idea 设置背景图片

    按下 Ctrl+Shift+A 你会看到一个对话框 在里面输入 Set Background Image 进入设置背景图片窗口 设置背景图,点击确定即可 就一个好看,强大的编程工具了

  5. hdu 超级楼梯 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2041 哦--对了,这些题读者可以直接忽略,我只是想练习一下自己薄弱的地方...... 题目意思我就不说 ...

  6. 让th里面的东西自动换行

    让th里面的东西自动换行 html中的TH里面的文字不管多长,始终是一行,很烦 <th style="word-wrap:break-word;">aaaaaaaaaa ...

  7. ComboBox联动 (AJAX BS实现)

    //从webservice中取数据ajax            Ext.Ajax.request({                url: 'WebService.asmx/GetComboxFi ...

  8. UVA-11054(扫描法)

    题意: n个等距村庄,每个村庄要么买酒要么卖酒,把k个单位的酒运到相邻村庄去需要k个单位的劳动力,问最少需要多少劳动力才能满足所有的村庄的要求; 思路: 上次做了一个环的,这个是直线的,就是一个大水题 ...

  9. 【USACO】 奶牛政坛

    [题目链接] 点击打开链接 [算法] tarjan算法求LCA [代码] #include<bits/stdc++.h> #define MAXN 200010 #pragma GOC o ...

  10. AutoIt: send 命令 VS ControlClick的使用

    2008年的时候第一次接触AutoIt,当时觉得局限性太多了,就不想学,觉得把Watir,Ruby搞好就行了. 最近一段时间比较闲,发现自己对GUI的自动化操完全是短板,就把AutoIt重新拾起来了. ...