python函数参数传递的秘密

BG05

Posted by Blue Geek on September 16, 2019

python函数参数传递的秘密

By 青衣极客 Blue Geek In 2019-09-16

跟一些python的程序员交流之后发现一个问题,那就是大家对函数参数传递的问题大多不是太清楚。按照实际使用来看,不清楚函数参数传递的一些秘密也不影响使用,但是一旦遇到与参数传递相关的BUG就蒙了。在C/C++中,传参的问题是专门讲述的,所以C/C++程序员对参数传递比较清楚。关于python函数的参数传递,这里简要讨论一下,让大家使用python时心里更加踏实一点。

1. 基本类型参数传递

基本类型就是int、float、bool这些内建基础类型。由于这些类型本身消耗的资源较少,所以传递的时候都是直接进行值传递。

a = 1
def func(a):
    a = 2
    return a
new_a = func(a)
print('a = ', a)
print('new_a = ', new_a)
a =  1
new_a =  2

结论: 基础类型直接实参值传递,函数内部使用一份复制品

2. 复合类型参数传递

复合类型一般都是比较复杂的,如果直接进行值传递会消耗比较多的资源,因此python中对复合类型采用引用传递的方式。这里会引起的问题是,函数内部对复合数据内容的修改会反映在函数外部,但是程序员以为对外面没有影响,从而出现BUG。

a = [1,2,3,4]
def func(a):
    a[1] = 10
    return a
new_a = func(a)
print('a = ', a)
print('new_a = ', new_a)
a =  [1, 10, 3, 4]
new_a =  [1, 10, 3, 4]

结论:复合类型传递该数据的引用,函数内部使用引用操作

3. 键值对传参

传参最直接的方式就是传实参名,但是如果对原来的函数进行扩充,那么传参就会错序。键值对的方式传参可以很好地解决这个问题。

def func(a, b):
    print('a={}, b={}'.format(a, b))
func(1, 2)
func(a=1, b=2)
func(b=2, a=1)
a=1, b=2
a=1, b=2
a=1, b=2

结论:使用键值对传参时,参数顺序无效

4. 元组传参

有时开发时会有不知道传参个数的情况,比如打印一串变量的时候。对于这种需求可以通过元组传参实现。

def func(*a):
    print('type(a)={}, a={}'.format(type(a), a))
func(1,2,3,4)
type(a)=<class 'tuple'>, a=(1, 2, 3, 4)

结论: 使用“*args”这种方式定义形参列表时,可以传任意参数,函数内部使用元组操作

5. 词典传参

为了解决任意传参的顺序困扰,还可以使用词典传参。

def func(**a):
    print('type(a)={}, a={}'.format(type(a), a))
func(a=1, b=2)
type(a)=<class 'dict'>, a={'a': 1, 'b': 2}

结论: 使用”**kwargs”这种方式定义形参列表时,使用键值对的方式传参,函数内部使用词典操作

对于一般的函数直接使用参数名和键值对的方式传参就行,这也是大多数情况下使用的方式。对于参数数量和参数名不明确的情况下,一般使用元组传参和词典传参相结合的方式,这在一些比较大型的项目中常用。

CHANGELOG

  • 2020-04-07 添加解说文本

【青衣极客】公众号



COMMENT

博客评论区功能由Github Issue提供,提交Issue时请以本文标题为话题

"BG05-python函数参数传递的秘密"