一, 不可变和可变参数

  • 在函数内部,针对参数使用赋值语句,不会影响调用函数时传递的实参变量。

无论传递的参数是可变还是不可变,只要针对参数使用的是赋值语句,在函数内部会修改局部变量的引用,不会影响到外部变量的引用。

  • 如果传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,同样会影响到外部数据。

当列表变量调用+=,实际是执行列表的extend()方法,会改变变量。

def demo(num, num_list):

    print("函数内部代码")
    
    num += num  # num = num + num
    # num_list.extend(num_list) 由于是调用方法
    # 函数执行结束后,外部数据同样会发生变化
    num_list += num_list

    print(num)
    print(num_list)
    print("函数代码完成")


if __name__ == "__main__":
    
    gl_num = 9
    gl_list = [1, 2, 3]
    print("原始列表:",gl_list,sep=' ')
    demo(gl_num, gl_list)
    print(gl_num)
    print(gl_list)

结果输出,调用函数后,gl_num值没有变化,但是fl_list列表增加了。

原始列表: [1, 2, 3]
函数内部代码
18
[1, 2, 3, 1, 2, 3]
函数代码完成
9
[1, 2, 3, 1, 2, 3]

二, 缺省参数

缺省参数的定义

  • 定义函数时,可以给某个参数指定一个默认值,具有默认值的参数叫做缺省参数。
  • 调用函数时,如果没有传入缺省参数的值,则在函数内部使用定义函数时指定的默认值。
  • 通常,将常见的值设置为缺省参数的默认值,从而简化函数的调用。

如下示例,函数print_info()中参数show为缺省参数,默认值是True;

  • print_info('hello,')会打印'hello,',因为show未传入就使用默认值;
  • print_info('python!',show=False)不会打印‘python!’,因为传入的show=False;
def print_info(s,show=True):
    '''
    params:
        @ s: 要打印的字符串
        @ show:是否打印字符串,缺省参数
    '''
    if show:
        print(s)
    else:
        pass


if __name__ == "__main__":
    print_info('hello,')
    print_info('python!',show=False)

显示结果:

hello,

缺省参数使用的注意事项

  • 缺省参数的定义位置:必须保证带有默认值的缺省参数在参数列表末尾。
  • 调用带有多个缺省参数的函数时,需要指定参数名,这样解释器才能知道参数的对应关系。

如下:

def print_info(s,show=True,title)  # 该种定义是错误的,缺省参数应该放在参数列表的末尾

def print_info(name,title="",company='',gender=True):
    '''
    params:
        @ name:名字
        @ title:职位名,默认是空
        @ company:公司名,默认是空
        @ gender:性别,默认是True男性,False是女性
    '''
    text = "男性"
    if not gender:
        text="女性"
    
    print('%s 是 %s, 是 %s 公司的 %s'%(name,text,company,title))


if __name__ == "__main__":
    print_info('mayun','albb')  # 本来是要输出 mayun 是 男性, 是 albb 公司的 
                                # 但是结果输出 mayun 是 男性, 是  公司的 albb
    print_info('mayun',company='albb')  # 输出:mayun 是 男性, 是 albb 公司的

三, 多值参数

有时需要一个函数能够处理的参数个数是不确定的,就需要用到多值参数。

python中有两种多值参数:

  • 参数名前加 * 表示可以接收元组;
  • 参数名前加 ** 表示可以接收字典;

通常给多值参数命名时,习惯使用以下两个名字:

  •  *args:存放元组参数;args是arguments的缩写,有变量的含义;
  •  **kwargs:存放字典参数;kw是keyword的缩写,kwargs表示键值对参数;

多值参数使用示例:计算任意多个数字的和

def cal_sums(*args):
    result=0

    for n in args:
        result += n
    
    return result

if __name__ == "__main__":
    print(cal_sums(1,2,3,4,5,6,7,8,9,0))

3.1 多值参数中元组和字典拆包

调用带有多值参数的函数时,如果希望 将一个元组变量,直接传递给args;将一个字典变量,直接传递给kwargs,那么就要使用拆包,简化参数的传递,拆包的方式:

  • 在元组变量前,增加 *;
  • 在字典变量前,增加 **;

示例如下:

def unpack(*args,**kwargs):
    print(args)
    print(kwargs)

if __name__ == "__main__":
    nums=(1,2,3)
    personInfo={'name':'xiao ming','age':18}
    print("未拆包:")
    unpack(nums,personInfo)
    print('拆包:')
    unpack(*nums,**personInfo)

输出结果,没有拆包时,传入的两个变量被认为是传递给args参数,拆包后,传入的两个变量分别被传递给args和kwargs。

未拆包:
((1, 2, 3), {'name': 'xiao ming', 'age': 18})
{}
拆包:
(1, 2, 3)
{'name': 'xiao ming', 'age': 18}