1.关键字参数
根据参数名来传入参数值,则无须遵守定义形参的顺序,这种方式被称为关键字参数。例如:
在调用函数时混合使用关键字参数和位置参数,则关键字参数一定要在位置参数之后。换句话说,关键字参数之后只能是关键字参数。
2.参数默认值
在某些情况下,程序需要在定义函数时为一个或多个形参指定默认值,在调用函数时就可以省略为该形参传入参数值,或直接使用该形参的默认值。
为形参指定默认值的语法格式如下:
形参名 = 默认值
例如:
3.参数收集
在形参前面添加一个一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入。例如:
参数收集的本质就是一个元组,Python将传给books参数的多个值收集成一个元组。
Python允许个数可变的形参可以处于形参列表的任意位置,但Python要求一个函数最多只能带一个支持’普通’参数收集的形参。如果需要给后面的参数传入参数值,则必须使用关键字参数;否则,程序会把所传入的多个值都当成是传给books参数的。
Python还可以收集关键字参数,此时Python会将这种关键字手机成字典。为了能让Python收集关键字参数,需要在参数前面加两个星号。在这种情况下,一个函数可以同时包含一个支持’普通’参数收集的参数和一个支持关键字收集的参数。例如:
4.逆向参数收集
逆向参数收集,是在程序已有列表,元组,字典等对象的前提下,把它们的元素"拆开"后传给函数的参数。
逆向参数收集需要在传入的列表,元组参数之前添加一个星号*,在字典参数前添加两个星号**。例如:
字典进行逆向参数收集时必须使用关键字参数的形式传入。demo_dic包含三个key-value对以关键字参数的形式传给test()函数。
5.函数的参数传递机制
Python中函数的参数传递机制都是"值传递"。所谓值传递,就是将实际参数值的副本传入函数,而参数本身不受影响。例如:
如果参数本身是一个可变对象(列表,字典等),此时Python也采用的是值传递方式。例如:
主程序中的dw是一个引用变量(也就是一个指针),它保存了字典对象的地址值,当把dw的值赋给swap()函数的dw参数后,就是让swap()函数的dw参数也保存这个地址值,即也会引用到同一个字典对象。
dw只是一个引用对象,此时系统复制的是dw变量,并未复制字典本身。
当程序在swap()函数中操作dw参数时,由于dw只是一个引用变量,故实际操作的还是字典对象,此时,不管是操作主程序中的dw变量,还是操作swap()函数里的dw参数,其实操作的都是他们共同引用的字典对象。
在swap()函数最后加一句dw = None
swap()函数中的dw变量不再指向任何对象,程序其他地方没有任何改变,主程序调用swap()函数后再次访问dw变量的a,b两个元素,依然可以输出9,6。可见,主程序中的dw变量没有受任何影响。
把swap()函数中的dw赋值为None后,在swap()函数中失去了对字典对象的引用,不可再访问该字典对象,但主程序中的dw变量不受任何影响,依然可以引用该字典对象,所以依然可以输出字典对象的a,b元素的值。
因此可以得出两个结论:
- 不管什么类型的参数,在Python函数中对参数直接使用"=“赋值是没有用的,直接使用”="赋值不能直接改变参数。
- 如果需要让函数修改某些数据,可以通过把这些数据包装成列表,字典等对象,然后把列表,字典等可变对象作为参数传入函数,在函数中通过列表,字典的方法修改他们,这样才能改变这些数据。
6.变量的作用域
不管是在函数的局部范围内还是全局范围内,都可能存在多个变量,每个变量"持有"该变量的值。从这个角度看,不管是局部范围内还是全局范围内,这些变量和它们的值就像一个"看不见"的字典,其中变量名是key,变量值是value。
实际上Python提供了三个工具函数来获取指定范围内大的"变量字典"
- globals():该函数返回全局范围内所有变量组成的"变量字典";
- locals():该函数返回当前局部范围内所有变量组成的"变量字典";
- vars(object):获取在指定对象范围内所有变量组成的"变量字典",如果不传入object参数,vars()函数和locals()函数作用完全相同。
globals()函数和locals()函数的区别和联系:
- locals()函数总是获取当前局部范围内的所有变量组成的"变量字典",因此,如果在全局范围内(在函数之外),调用locals()函数,同样会获得全局范围内所有变量组成的"变量字典",而globals()函数无论在哪里执行,总是获取全局范围内所有变量组成的"变量字典";
- 不管使用globals()函数还是locals()函数来获取全局范围内的"变量字典",“变量字典"都可以被修改。这种修改会真正改变全局变量本身,但通过locals()函数获取的局部范围内的"变量字典”,即使对它修改也不会真正影响局部变量。
def test():
age = 20
print(age)
#访问函数局部范围内的"变量字典"
print(locals())
#通过函数局部范围内的"变量字典"访问age变量
print(locals()['age'])
#通过locals()函数局部范围内的"变量字典"改变age变量
locals()['age'] = 12
print(age)
#通过globals()函数修改x全局变量
globals()['x'] = 19
test()
x = 5
y = 20
print(globals())
#在全局范围内使用locals()函数访问的是全局变量的"变量数组"
print(locals())
print(x)
#通过全局变量的"变量数组"访问x全局变量
print(globals()['x'])
#通过全局变量的"变量数组"对x全局变量赋值
globals()['x'] = 39
print(x)
#在全局范围内使用locals()函数对x全局变量赋值
locals()['x'] = 99
print(x)
运行结果如下:
全局变量默认可以在所有函数内进行访问:但如果在函数中定义了与全局变量同名的局部变量就会发生局部变量遮掩全局变量的情形。例如:
该错误提示test()函数中的name变量还未被定义,。Python语法规定:在函数内部对不存在的变量赋值时,默认就是重新定义新的局部变量。因此这行代码相当于重新定义了name局部变量,这样,name全局变量就被遮掩了。
为了避免这种情况,有两种方法:
- 访问被遮蔽的全局变量:
如果程序希望test()函数依然能访问全局变量name,可以通过globals()函数实现:
2.在函数中声明全局变量
为避免在函数中对全局变量的赋值(不是重新定义局部变量),可以使用global语句来声明全局变量。