Chinaunix首页 | 论坛 | 博客
  • 博客访问: 533009
  • 博文数量: 174
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 1827
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-15 14:12
文章分类

全部博文(174)

文章存档

2018年(1)

2017年(1)

2013年(3)

2012年(9)

2010年(12)

2009年(5)

2008年(106)

2007年(37)

我的朋友

分类: Python/Ruby

2008-12-25 10:54:34

    python函数参数与命令行参数

    python中函数参数的传递是通过赋值来传递的。函数参数的使用又有俩个方面值得注意:
    1.函数参数是如何定义的  
    2.在调用函数的过程中参数是如何被解析

    先看第一个问题,在python中函数参数的定义主要有四种方式:

    1.F(arg1,arg2,...)
    这是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参。例如:
    def a(x,y):
        print x,y
    调用该函数,a(1,2)则x取1,y取2,形参与实参相对应,如果a(1)或者a(1,2,3)则会报错。

    再看下面的例子:
    >>> a=(1,2,3)
    >>> def printpa(a):
    ...    print type(a)
    ...    print a
    ...
    >>> printpa(a)
   
    (1, 2, 3)
    >>> printpa(range(1,4))
   
    [1, 2, 3]
    >>> printpa({})
   
    {}
    >>> def printpa(a,b,c):
    ...   print a,b,c
    ...
    >>> printpa(a)
    Traceback (most recent call last):
      File "", line 1, in
    TypeError: printpa() takes exactly 3 arguments (1 given)
    >>> printpa(*a)
    1 2 3
    >>> a=[1,2,3]
    >>> printpa(*a)
    1 2 3
    >>> printpa(a)
    Traceback (most recent call last):
      File "", line 1, in
    TypeError: printpa() takes exactly 3 arguments (1 given)
    >>> a=[1,2,3,4]
    >>> printpa(*a)
    Traceback (most recent call last):
      File "", line 1, in
    TypeError: printpa() takes exactly 3 arguments (4 given)
    >>> printpa(*range(1,4))
    1 2 3
    由上可以看出,如果函数的有多个形参,调用的时候可以传递一个元组或列表来作实参,但是元组或列表中元素的个数必须与形参的个数相同。

    2.F(arg1,arg2=value2,...)
    这种方式就是第一种的改进版,提供了默认值
    def a(x,y=3):
        print x,y
    调用该函数,a(1,2)同样还是x取1,y取2,但是如果a(1),则不会报错了,这个时候x还是1,y则为默认的3。上面这俩种方式,还可以更换参数位置,比如a(y=8,x=3)用这种形式也是可以的。

    例子:
    >>> def printpa(a=3,b=4):
    ...   print a,b
    ...
    >>> printpa(1)
    1 4
    >>> printpa(1,2)
    1 2
    >>> printpa(b=5)
    3 5
    >>> printpa(b=5,a=2)
    2 5


    3.F(*arg1)
    上面俩个方式是有多少个形参,就传进去多少个实参,但有时候会不确定有多少个参数,则此时第三种方式就比较有用,它以一个*加上形参名的方式来表示这个函数的实参个数不定,可能为0个也可能为n个。注意一点是,不管有多少个,在函数内部都被存放在以形参名为标识符的tuple中。

    >>> def printpa(*a):
    ...    print type(a)
    ...    print a
    ...
    >>> printpa(1)
   
    (1,)
    >>> printpa(1,2)
   
    (1, 2)
    >>> printpa(1,2,3)
   
    (1, 2, 3)
    >>> printpa(1,2,[1,2])
   
    (1, 2, [1, 2])
    >>> printpa(1,2,(1,2))
   
    (1, 2, (1, 2))
    >>> printpa(1,2,{"aa":1,"bb":2})
   
    (1, 2, {'aa': 1, 'bb': 2})

    4.F(**arg1)
    形参名前加俩个*表示,参数在函数内部将被存放在以形式名为标识符的dictionary中,这时调用函数的方法则需要采用arg1=value1,arg2=value2这样的形式。


    >>> def printpa(**a):
    ...    print type(a)
    ...    print a
    ...
    >>> printpa(a=1,y=2)
   
    {'a': 1, 'y': 2}
    >>> printpa(a=1)
   
    {'a': 1}
    >>> li=[1,2,3,4]
    >>> printpa(b=li)
   
    {'b': [1, 2, 3, 4]}
    >>> tu=(1,2,3)
    >>> printpa(b=tu)
   
    {'b': (1, 2, 3)}
    >>> printpa(1,2)
    Traceback (most recent call last):
      File "", line 1, in
    TypeError: printpa() takes exactly 0 arguments (2 given)


    上面说了四种函数形式定义的方式以及他们的调用方式,是分开说的,其实这四种方式可以组合在一起形成复杂多样的形参定义形式。在定义或调用这种函数时,要遵循以下规则:

    1. arg=必须在arg后
    2. *arg必须在arg=后
    3. **arg必须在*arg后

    在函数调用过程中,形参赋值的过程是这样的:

    首先按顺序把“arg”这种形式的实参给对应的形参
    第二,把“arg=”这种形式的实参赋值给形式
    第三,把多出来的“arg”这种形式的实参组成一个tuple给带一个星号的形参
    第四,把多出来的“key=value”这种形式的实参转为一个dictionary给带两个星号的形参。

    听起来好复杂,实际是是很简单的。很直观,来看例子:

    >>> def test(x,y=1,*a,**b):
     print x,y,a,b


    >>> test(1)
    1 1 () {}
    >>> test(1,2)
    1 2 () {}
    >>> test(1,2,3)
    1 2 (3,) {}
    >>> test(1,2,3,4)
    1 2 (3, 4) {}
    >>> test(x=1,y=2)
    1 2 () {}
    >>> test(1,a=2)
    1 1 () {'a': 2}
    >>> test(1,2,3,a=4)
    1 2 (3,) {'a': 4}
    >>> test(1,2,3,y=4)

    Traceback (most recent call last):
      File "", line 1, in -toplevel-
        test(1,2,3,y=4)
    TypeError: test() got multiple values for keyword argument 'y'


   最后,来说一点关于命令行参数的问题。习惯了 C/C++ 语言,甚至是 shell 里面,在写 usage()函数的时候,就想当然的调用了 sys.argc 来获得命令行参数的个数,结果当然会出错了,sys模块中是没有提供 argc 属性的,但是如果我们意识到命令行参数实际上是一个列表的话,就很容易得到参数的个数,如下所示:

    $ cat argvtype.py
    #! /usr/bin/env python

    import sys

    print "The num of commandline argument is %d"% len(sys.argv)
    print "The type of commanline argument is %s"% type(sys.argv)
    print "The commandline argument list: ",sys.argv


    $ ./argvtype.py tt1 tt2 tt3
    The num of commandline argument is 4
    The type of commanline argument is
    The commandline argument list:  ['./argvtype.py', 'tt1', 'tt2', 'tt3']




参考资料:
Python函数中的变长参数            http://blog.chinaunix.net/u2/62895/showart_1073240.html
Python中函数的参数定义和可变参数        http://blog.csdn.net/FeiSan/archive/2007/08/07/1729905.aspx
python的函数参数                http://milkpopo.blogspot.com/2008/10/python.html
Python 函数参数的传递(转)        %E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E7%9A%84%E4%BC%A0%E9%80%92%E8%BD%AC/
     
python 函数参数的传递           
阅读(1428) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~