函数进阶
使用元组返回多个值
def measure():
temp = 39
wetness = 50
return (temp,wetness)
如果函数返回值是一个元组,小括号可以省略
def measure():
temp = 39
wetness = 50
return temp,wetness
res = measure()
print(res[0])
print(res[1])
上述代码需要一次接收多个返回值,并且函数调用者不清楚返回的元组长度是多少,容易导致下标越界报错,可以使用多个变量,一次接收函数的返回结果
gl_temp,gl_wetness = measure()
print(gl_temp)
print(gl_wetness)
使用这种多个变量获取方法执行结果时,不能定义超过函数返回元组中元素格式的变量,否则会导致程序报错
使用元组完成数据交换
# 普通方法
def normal_swap(a, b):
c = a
a = b
b = c
return a, b
# 普通方法,但是不定义临时变量
def swap_without_tempvar(a, b):
a += b
b = a - b
a -= b
return a, b
# python独有的方法
def unique_python_swap(a, b):
# 等号右边是一个元组,只是把小括号省略了
a, b = b, a
return a, b
a = 4
b = 3
print("交换之前a = %d ,b= %d" % (a, b))
a, b = normal_swap(a, b)
print("交换之后a = %d ,b= %d" % (a, b))
print("交换之前a = %d ,b= %d" % (a, b))
a, b = swap_without_tempvar(a, b)
print("交换之后a = %d ,b= %d" % (a, b))
print("交换之前a = %d ,b= %d" % (a, b))
a, b = unique_python_swap(a, b)
print("交换之后a = %d ,b= %d" % (a, b))
函数的参数
在函数内部使用赋值语句修改参数的值,不会影响外部实参变量
gl_num = 99
gl_name_list = [1, 2, 3]
# 定义change参数的时候,一般不会使用全局变量作为形式参数
# 此处使用只是为了明确:在整个代码执行过程中,参数值在函数内部修改后不影响外部的全局变量
def change(gl_num, gl_name_list):
print("调用时,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用时,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
gl_num = 200
gl_name_list = [4, 5, 6]
print("函数中,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用时,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
change(gl_num, gl_name_list)
print("调用后,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用后,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
调用时,第一个参数的地址为: 7ff95124d5f8 ,值为: 99.000000
调用时,第二个参数的地址为: 2b7cc03d100 ,值为: [1, 2, 3]
函数中,第一个参数的地址为: 7ff95124e298 ,值为: 200.000000
调用时,第二个参数的地址为: 2b7cc16f400 ,值为: [4, 5, 6]
调用后,第一个参数的地址为: 7ff95124d5f8 ,值为: 99.000000
调用后,第二个参数的地址为: 2b7cc03d100 ,值为: [1, 2, 3]
由上述代码可以看出,无论参数是可变的还是不可变的,会在函数内部修改局部变量的引用,不会影响到外部变量的引用。
gl_num = 99
gl_name_list = [1, 2, 3]
def change(gl_num, gl_name_list):
print("调用时,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用时,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
gl_num = 200
# gl_name_list = [4, 5, 6]
gl_name_list.append(7)
temp_list = [8,9]
gl_name_list.extend(temp_list) # 这句话与 gl_name_list += temp_list 相当
print("函数中,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用时,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
change(gl_num, gl_name_list)
print("调用后,第一个参数的地址为: %x ,值为: %f" % (id(gl_num), gl_num))
print("调用后,第二个参数的地址为: %x ,值为: %s" % (id(gl_name_list), gl_name_list))
调用时,第一个参数的地址为: 7ff95124d5f8 ,值为: 99.000000
调用时,第二个参数的地址为: 1f96b09d100 ,值为: [1, 2, 3]
函数中,第一个参数的地址为: 7ff95124e298 ,值为: 200.000000
调用时,第二个参数的地址为: 1f96b09d100 ,值为: [1, 2, 3, 7, 8, 9]
调用后,第一个参数的地址为: 7ff95124d5f8 ,值为: 99.000000
调用后,第二个参数的地址为: 1f96b09d100 ,值为: [1, 2, 3, 7, 8, 9]
如果传入的数据类型是可变类型,并在方法中,调用方法完成了数据内容的修改,会影响到外部变量
缺省参数
- 定义函数时,可以给 某个参数 指定一个默认值,具有默认值的参数,被称为缺省参数
- 调用函数时,如果没有传入缺省参数 ,在执行过程中,函数会使用参数的默认值
- 缺省参数,为常见的变量赋予默认值,方便函数的调用个
gl_list = [1, 2, 3]
# 按照升序排序
gl_list.sort()
# 按照降序排序
gl_list.sort(reverse = True)
定义函数的缺省参数
def employee_info(name, title, is_admin=False):
if is_admin:
permission = "have all permission"
else:
permission = "have normal permission"
print("My name is %s, i am a / an % s, My permission is '%s' " % (name, title, permission))
employee_info('Steve', 'employee')
employee_info('Tim', 'boss', True)
Tips:
- 在指定缺省参数的默认值时,优先使用常见的默认值
- 如果一个参数的默认值不能确认,不需要使用默认值
- 缺省参数可以有多个,但是均应置于普通参数后面
- 在调用含有多个缺省参数的方法时,如果传入了某个缺省参数的值,应该使用 缺省参数 = 具体值 作为实参,方便解释器明白修改了被调用函数的缺省参数
多值参数
在实际开发过程中,会遇到这种情况,一个方法的参数个数不固定。这个时候就可以使用多值参数
- python 有两种多值参数
- 参数名前面加 * ,可以接收元组
- 参数名前面加 ** , 可以接收字典
- 一般给多值参数命名时,习惯使用下面两个参数
- *args 存放元组参数
- **kwargs 存放数组参数
def demo(name, *args, **kwargs):
print(name)
print(args)
print(kwargs)
demo(1) # 1 () {}
demo(1, 2, 3, 4, 5) # 1 (2,3,4,5) {}
demo(1, 2, 3, 5, 6, a=1, b=2) # 1 (1, 2, 3, 4, 5) {'a': 'Steve', 'b': 18}
使用多值参数完成任意数字求和
def sum_tuple(*args):
result = 0
for i in args:
result += i
return result
print(sum_tuple(1, 2, 3, 4, 5))
元组和字典的拆包
- 在调用多值参数的函数时,有如下需求
- 将一个元组变量,直接传递给 args
- 将一个字典变量,直接传递给 kwargs
- 就可以使用拆包,简化参数的传递
- 在元组变量前,增加一个 *
- 在字典变量前,增加一个 **
def demo(name, *args, **kwargs):
print(name)
print(args)
print(kwargs)
info = {'a': 'Steve', 'b': 18}
init_tuple = (1, 2, 3, 4, 5)
demo(1, *init_tuple, **info)
函数的递归
递归函数的特点
自己调用自己
递归函数的代码特点
- 函数每次执行代码的逻辑是相同的,只是针对参数不同,处理的结果不同
- 为避免死循环的情况出现,需要定义一个条件,满足条件的时候,递归停止
代码示例
# 使用递归的方法,给定一个整数值作为公差为1的数列的最后一项,求这个数列的前几项和(数列第一项为1)
def recur_add(num):
if num == 1:
return 1
result = recur_add(num - 1)
return num + result
print(recur_add(3))