前言

函数式编程是初学者最先接触到的编程方法,下面主要介绍python中函数传参的几种不同的形式。

传参的基本形式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a, b):
    print(a+b)

if __name__ == '__main__':
    functionname(1, 2)

结果:

3

一般形式下的函数传参,实参和形参的数目必须要对应,否则会报错。

In [1]: def fun_name(a, b):
   ...:     print(a+b)

In [2]: fun_name(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-cfcdf16293c7> in <module>()
----> 1 fun_name(1)

TypeError: fun_name() takes exactly 2 arguments (1 given)

In [3]: fun_name(1, 2, 3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-8f24614dfc73> in <module>()
----> 1 fun_name(1, 2, 3)

TypeError: fun_name() takes exactly 2 arguments (3 given)

缺省参数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a, b='china', cc=1111):
    print("my name is %s"%a)
    print("my address is %s"%b)
    print("my phone is %d"%c)


if __name__ == '__main__':
    name = raw_input('ENTER your name:')
    # 示例使用的Python 2.7.5,python3使用input()
    functionname(name)

结果

ENTER your name:zhang
my name is zhang

可以看到,函数的参数只传了一个name,b和c是用默认的参数代替,当然,如果对缺省参数传参的话,默认的参数会被覆盖。
需要注意的地方是,缺省参数一定要写在正常传参的后面,不然会报错non-default argument follows default argument,同时要注意传参的顺序。

In [4]: def fun_name(name='zhang', addr):
   ...:     print(name)
   ...:     
  File "<ipython-input-4-ca7d69b85b54>", line 1
    def fun_name(name='zhang', addr):
SyntaxError: non-default argument follows default argument

命名参数

命名参数也称之为关键字参数, 其仅针对函数的调用, 让调用者通过函数调用中的参数名字赋值来将实参映射到形参。可以以乱序的形式调用传参。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a, b, c):
    print("my name is %s"%a)
    print("my address is %s"%b)
    print("my phone is %s"%c)


if __name__ == '__main__':
    name = raw_input('ENTER your name:')
    addr = raw_input('ENTER your address:')
    phone = raw_input('ENTER your phone numbers:')
    # 示例使用的Python 2.7.5,python3使用input()
    functionname(c=phone, b=addr, a=name )
    # 注意这里没有按照顺序传参

结果

ENTER your name:zhang
ENTER your address:china
ENTER your phone numbers:1111
my name is zhang
my address is china
my phone is 1111

命名参数可以和缺省参数一块使用。在缺省参数的示例中,地址、电话号码已经有默认参数,假如只想更改默认的电话号码,不想更改地址,也必须传入三个参数,不可以缺省地址,因为参数是按照顺序传入的,而使用命名参数可以实现只传入两个参数。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a, b='china', c='1111'):
    print("my name is %s"%a)
    print("my address is %s"%b)
    print("my phone is %s"%c)


if __name__ == '__main__':
    name = raw_input('ENTER your name:')
    addr = raw_input('ENTER your address:')
    phone = raw_input('ENTER your phone numbers:')
    # 示例使用的Python 2.7.5,python3使用input()
    functionname(c=phone, a=name )
    # 缺省了地址

结果

ENTER your name:zhang
ENTER your address:nanjing
ENTER your phone numbers:33333
my name is zhang
my address is china
my phone is 33333

不定长参数

函数传参时形参和实参的数目要对应,缺省参数可以少传参,但要注意传参的顺序,那么假如函数传参的数量不确定,想要传入比预定数量多的参数,就要使用不定长参数。

def functionname(*args, **kwargs)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a, *args):
    print(a)
    print(args)
    # 多余的参数以元组形式保存
if __name__ == '__main__':
    name = raw_input('ENTER your name:')
    addr = raw_input('ENTER your address:')
    phone = raw_input('ENTER your phone numbers:')
    # 示例使用的Python 2.7.5,python3使用input()
    functionname(name, addr, phone)

结果

ENTER your name:zhang
ENTER your address:china
ENTER your phone numbers:22222
zhang
('china', '22222')
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def functionname(a,**args):
    print(a)
    print(args)
    # 多余参数保存为字典


if __name__ == '__main__':
    Enter1 = raw_input('ENTER your name:')
    Enter2 = raw_input('ENTER your address:')
    Enter3 = raw_input('ENTER your phone numbers:')
    # 示例使用的Python 2.7.5,python3使用input()
    functionname(Enter1, addr=Enter2, phone=Enter3)

结果
functionname(Enter1, addr=Enter2, phone=Enter3)注意这里不是命名参数,而是多余参数以字典形式保存,这里传入的是字典的键值对。

ENTER your name:zhang
ENTER your address:china
ENTER your phone numbers:1111
zhang
{'phone': '1111', 'addr': 'china'}

假如没有多余的参数传入也不会报错,仅仅为空元组和空字典。

In [1]: def fun(a, *args, **kwargs):
   ...:     print(a)
   ...:     print(args)
   ...:     print(kwargs)
   ...:     

In [2]: fun(11)
11
()
{}

匿名函数lambda

匿名函数无须使用def关键字来进行声明。,因此也不用起函数名。
lambda函数可以接受任何数量的实参,但只会且仅返回一个表达式的值。
lambda函数不能包含有命令和多个表达式。
lambda函数拥有自己的命名空间,不能访问除自身参数列表之外的全局命名空间内的参数。
lambda最大的优势在于,可以不占用栈内存从而增加执行效率。
lambda函数的定义格式:

functionName = lambda [arg1[,arg2,…]]:expression

In [3]: n = lambda x,y:pow(x,y)

In [4]: type(n)
Out[4]: function

In [5]: n(3,2)
Out[5]: 9

In [6]: type(n(3,2))
Out[6]: int

多类型传入

其实不定长参数本质是将冗余的实参转换为Tuple数据类型后再传递给函数。下面的例子传递了一个Tuple类型实参给函数,和使用不定长参数效果是一样的。需要注意的是,不定长参数需要放到函数形参列表的后端,而Tuple类型形参可以随意放置。

# coding:utf-8
def fun_name(a, b):
    print(a)
    print(b)

if __name__ == '__main__':
    name_tuple = ('a', 'b', 'c', 'd')
    fun_name(name_tuple, 'e')

结果

('a', 'b', 'c', 'd')
e

当然也可以通过解包来限定只允许传入元组,*代表解包,迭代取元组的值。

# coding:utf-8
def fun_name(a, b, c ,d):
    print(a+b+c+d)


if __name__ == '__main__':
    name_tuple = ('a', 'b', 'c', 'd')
    fun_name(*name_tuple)#解包

结果

abcd

当然也可以传入列表和字典。

# coding:utf-8
def fun_name(a, b, c, d):
    print(a+b+c+d)


if __name__ == '__main__':
    name_list = ['a', 'b', 'c', 'd']
    fun_name(*name_list)
# coding:utf-8
def fun_name(a, b):
    print(a)
    for var in b:
        print(b[var])


if __name__ == '__main__':
    dic = {'name':"zhang", 'addr':'china', 'phone':"111"}
    fun_name('a',dic)

结果

a
zhang
china
111

后言

增强型赋值语句

In [1]: Li = ['a', 'b']

In [2]: id(Li)
Out[2]: 30946944

In [3]: Li += ['c']

In [4]: id(Li)
Out[4]: 30946944

普通型赋值语句

In [1]: Li = ['a', 'b']

In [2]: id(Li)
Out[2]: 40478624

In [3]: Li = Li + ['c','d']

In [4]: id(Li)
Out[4]: 42890880