再学函数
局部变量和全局变量
请大家运行如下代码
这段代码中,函数里面和函数外面都定义了一个名字为var 的变量。
在函数里面和函数外面都执行打印语句,输出 var 变量的值
运行一下,就会发现输入如下结果
在函数外面定义的变量称之为 全局(global)变量
在函数里面定义的变量称之为 局部(local)变量
如果在函数内部有 变量赋值语句,且该变量名和全局变量相同,会产生一个新的局部变量,而不是将全局变量进行重新赋值。
同名的局部变量和全局变量,虽然它们两个名字相同,但其实它们是不同的变量,指向不同的对象。
刚才的运行结果说明了:如果全局变量和局部变量同名,函数体里面的代码使用的是局部变量。
如果不是赋值语句,函数里面可以直接使用外部的全局变量,比如
运行结果是
那么如果我们就是需要在函数内部 把全局变量进行重新赋值,该怎么办呢?
这时,就需要我们在函数内部使用 global
关键字声明,使用的是全局变量。
比如
var = '桌子'
def test():
global var
var = '椅子'
print(f"在函数中,var的值是:{var}")
test()
print(f"在函数外,var的值是:{var}")
调用test函数的时候, 由于 global var
声明了:在函数内部的变量var就是全局变量var,所以下面的这条语句就改变了 全局变量var的值
在函数调用结束后, 全局变量var的值产生了相应的改变。
所以运行结果如下:
可变参数
假设我们有这样的一个字典,存储学生年龄,如下:
要实现一个函数 printAge
,它的输入参数是一些学生的姓名,函数需要打印出这些输入学生的年龄。
这里有个问题,就是调用printAge 时, 输入的学生名字 个数是不固定的,可能是1个、2个、100个, 甚至也可能是0个。
这肯定难不倒聪明的你, 你一番思考,决定使用列表作为参数类型, 列表里面每个元素存放要获取年龄信息的学生名。
像这样
studentInfo = {
'张飞' : 18,
'赵云' : 17,
'许褚' : 16,
'典韦' : 18,
'关羽' : 19,
}
def printAge(students) :
for student in students:
print( f'学生:{student} , 年龄 {studentInfo[student]}')
printAge(['张飞', '典韦', '关羽'])
printAge(['赵云'])
运行一下看看, 完全没有问题。
但是我们似乎觉得,如果调用该函数的时候,能把下面这种写法
改为
这样调用。 显得更加易读易懂。
但是问题就在于,因为这个函数参数的个数是不确定的,函数如何定义呢?
Python中可以这样定义
def printAge(*students) :
for student in students:
print( f'学生:{student} , 年龄 {studentInfo[student]}')
和上面相比,唯一的改动就是, 参数名前面加了一个星号。
然后我们就可以这样调用该函数了
效果和前面一种定义完全一样。
这种前面加一个星号的参数,称之为可变参数,
在调用该函数的时候,Python解释器会创建一个 tuple 赋值给这个参数变量。并且会把 传入的数据对象 放到这个tuple对象里面。
也就是说,上面的例子里面,如下调用代码执行的时候,
Python解释器创建一个 tuple 赋值给这个 students,里面存放了 '张飞', '典韦', '关羽' 三个字符串对象作为元素,我们在代码里加入一行语句,显示 students 类型
studentInfo = {
'张飞' : 18,
'赵云' : 17,
'许褚' : 16,
'典韦' : 18,
'关羽' : 19,
}
def printAge(*students) :
print(type(students))
for student in students:
print( f'学生:{student} , 年龄 {studentInfo[student]}')
printAge('张飞', '典韦', '关羽')
运行结果显示
说明 students变量确实是对应一个tuple对象。
printAge 使用上面这样的可变参数,假如我们要传入的参数恰好已经在一个list(或者tuple) 中,比如
怎么调用printAge呢?
当然可以这样
printAge (onebatch[0], onebatch[1], onebatch[2])
显然不方便。
其实,我们可以这样
在调用时,这就是参数展开。
我们可以将其等价于
大家注意,这里是在调用函数的时候,传入参数前面加上星号,是参数展开;
前面我们讲的可变参数是在函数定义的时候前面加上星号。
大家不要搞混了。
关键字可变参数
参数个数不确定,除了上面这种定义的方式,还有另外一种定义方式,叫做关键字可变参数。
比如,我们要实现一个函数,可以在 学生年龄表里面添加新的学生信息, 可以输入不定数量的学生信息,包括姓名和年龄。
可以这样定义
def addStudents(table,**students):
print(type(students))
for name,age in students.items():
table[name] = age
table1 = {}
table2 = {}
addStudents(table1, 李白=20, 杜甫=24)
addStudents(table2, Jodan=45, James=32, onil=40)
print(table1)
print('----------------')
print(table2)
运行一下,输出结果如下
<class 'dict'>
<class 'dict'>
{'李白': 20, '杜甫': 24}
----------------
{'Jodan': 45, 'James': 32, 'onil': 40}
其中 <class 'dict'>
说明了 前面有两个星号 的 参数变量 students
的值是一个字典。
这种前面加2个星号的参数,称之为关键字可变参数,
在调用该函数的时候,Python解释器会创建一个 dict (字典) 赋值给这个参数变量。
并且会把 传入的数据对象 分别放到这个dict 对象里面。
传入的参数对象,必须是像 name=value
这种 带参数名和参数值的, 放到dict对象时,参数名是字典元素的key,参数值是字典元素的value。
也就是说,上面的例子里面,如下调用代码执行的时候,
Python解释器创建一个 字典 赋值给参数变量 students,把李白,20
和 杜甫,24
作为 2个键值对元素放到 该字典中。
addStudents 使用上面这样的关键字可变参数,假如我们要传入的参数恰好已经在一个字典 中,比如
怎么调用addStudents呢?
可以这样参数展开
和上面不同的是,对字典,要使用两个星号进行参数展开,Python解释器会把字典里面,每个元素的键作为参数名,值作为参数值,这样进行函数调用