10 Python学习之函数
通过函数我们可以实现代码的重复利用,使代码简介,重复利用率高,
函数的定义
语法:
def 函数名(参数):
函数体
返回值
注意:
- def是关键字,不可省略
- 参数不是必须的,也可以无参
- 函数体可以有返回值,也可以没有
- 函数的调用是函数名 + 括号
例1:
def add(): # 定义函数,无参,无返回值
print(3 + 5)
add() # 函数的调用
返回值
函数用return返回执行后的信息,return不是必须的,函数中在return后面的语句不会执行
如果需要返回多个值,每个值之间用逗号隔开,返回的结果是一个元组
例1:
def add():
sum = 3 + 5
return sum # 返回sum
print("函数结束") # 不会打印,位于return后面的语句都没有意义
ret = add() # ret接受add函数中return返回的sum的值
print(ret)
例2:
def add():
return 3, 4, 5 # 返回多个值
ret = add()
print(type(ret)) # 打印返回值的类型
函数的参数
函数的参数分为:位置参数、关键字参数、默认参数、
函数定义时括号中的参数,我们称为形参
调用函数时,传入的参数,我们称为实参
例1:
def add(num1, num2): # 这里num1和num2是形参
return num1 + num2
ret = add(3, 5) # 这里3和5是实参
print(ret)
位置参数
位置参数传参,形参和实参从左至右必须一一对应,如果不对应,可能会得到意想不到的结果
例1:
def info(name, age, gender):
print('姓名:%s, 年龄:%s, 性别:%s ' % (name, age, gender))
info('张三', '男', 18)
运行结果是:
姓名:张三, 年龄:男, 性别:18 # 正常age应该传18,gender应该传'男'
说明:
这里位置参数
张三传递给形参name,男传递给形参age,18传递给形参gender,形参位置是一一对应,如果位置错误,就不会得到我们要的结果。
关键字参数
关键字参数是指在传实参的时候,指定 形参 = 实参
的的格式,关键字参数无需考虑顺序,但必须放在位置参数的后面,否则位置参数会报错
例1:
def info(name, age, gender):
print('姓名:%s, 年龄:%s, 性别:%s ' % (name, age, gender))
info(name='张三', gender='男', age=18) # 关键字参数,无需考虑顺序
运行结果:
姓名:张三, 年龄:18, 性别:男 # 结果完全正确
位置参数和关键字参数的混合使用
位置参数必须全部位于关键字参数的前面
例1:
def info(name, age, gender):
print('姓名:%s, 年龄:%s, 性别:%s ' % (name, age, gender))
info('张三', gender='男', age=18) # 位置参数必须位于关键字参数的前面
# info('张三', gender='男', 18) # 报错,无法运行
默认值参数
默认值参数是函数的形参有一个默认的值,我们在调用函数的时候,可以不给这个参数传值,如果不传就用形参默认的值,如果传了(不管是按位置参数还是关键字参数传的)就使用传入的值,默认值参数一般用于经常使用的参数
默认参数在定义的时候也必须放在位置形参的后面
例1:
def info(name, gender, age=18): # 默认参数,age=18
print('姓名:%s, 年龄:%s, 性别:%s ' % (name, age, gender))
info('张三', '男') # 不传age
info('李四', '男', 24) # 用位置参数的方式传入
info(name='王五', gender='男', age=28) # 用关键字参数的方式传入
运行结果:
姓名:张三, 年龄:18, 性别:男
姓名:李四, 年龄:24, 性别:男
姓名:王五, 年龄:28, 性别:男
不定长位置参数
不定长参数,可以在定义函数时不确定参数个数时,而又必须接收全部传入的实参
不定长参数接收的是位置参数,也称为可变位置参数定义方式是在位置参数前面加一个星号(*),不定长参数接收后是一个元组
例1:
def info(name, age, *args):
print(type(args))
print("我叫%s, 今年 %s 岁, 喜欢吃:%s" % (name, age, args))
info("张三", 19, '花菜', '萝卜', '鱼', '大白菜', '鸡肉', '土豆', '茄子')
不定长关键字参数
不定长关键字参数跟不定长参数类似,它接收的是关键字参数,不定长关键字参数接收后是一个字典
例1:
def info(**kwargs):
print(kwargs)
info(name="张三", age='18', gender='男')
运行结果:
{'name': '张三', 'age': '18', 'gender': '男'} # 打印结果是一个字典
五种类型参数在定义函数时的位置
位置参数—不定长位置参数—默认参数—不定长关键字参数
注意:
不定长位置参数(*args)和默认参数位置可以互换,因为默认参数如果放在不定长位置参数前面,会按位置参数去传,如果默认参数放在不定长参数后面,如果需要给默认参数传值必须使用关键字参数,否则就会被不定长参数接收
例1:
默认参数在不定长位置参数前
def info(name, age, gender='', *args, **kwargs):
print(name)
print(age)
print(gender)
print(args)
print(kwargs)
info("张三", '18', '男', '吃', '喝', '玩', hobby='骑行')
例2:
默认参数在不定长位置参数后,给默认参数赋值,必须使用关键字参数
def info(name, age, *args, gender='', **kwargs):
print(name)
print(age)
print(gender)
print(args)
print(kwargs)
# 使用关键字参数对默认参数进行传值
info("张三", '18', '男', '吃', '喝', '玩', gender='女', hobby='骑行')
全局变量和局部变量
全局变量
全局变量我们可以直接使用,全局变量是定义在类里面或者在函数的外部
例1:
house = '清华大学' # 全局变量
def func1():
print("在函数func1中调用全局变量:%s" % house) # 在函数内部调用全局变量
func1() # 调用函数
print("在函数外部调用全局变量:%s" % house)
运行结果:
在函数func1中调用全局变量:清华大学
在函数外部调用全局变量:清华大学
局部变量
局部变量是在函数内部定义的,他的作用范围只在函数内,出了函数就没用了
例1:
house = '清华大学' # 全局变量
def func1():
myhouse = "北京大学"
print("局部变量:%s" % myhouse)
func1() # 调用函数
# print("在函数外部调用局部变量:%s" % myhouse) # 无法调用局部变量
局部变量在正常情况下是无法改变全局变量的值的(指的是字符类型和整数类型,列表和字典可变类型,局部变量是可以修改的,因为这些是引用),除非在定义的时候声明了global
例2:
house = '清华大学' # 全局变量
def func1():
global house # 如果此处不声明,是无法修改的
house = "北京大学"
print("修改全局变量:%s" % house)
print("调用前的全局变量:%s" % house)
func1() # 调用函数
print("调用后的全局变量:%s" % house) # 全局变量house的值已经改变了
运行结果:
调用前的全局变量:清华大学
修改全局变量:北京大学
调用后的全局变量:北京大学
递归函数
如果一个函数再内部调用自身,那么称这个函数为递归函数
递归的特性:
- 必须有一个明确的结束条件
- 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 递归效率不高,层次过多会导致栈溢出(在计算机中,函数调用时通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈机会减一层栈帧,由于栈的大小不是无限的,所以,递归调用次数过多,会导致栈溢出,大概在1000次的时候,就会溢出)
例1:
递归计算1+2+...+100的和
def func(num):
if num == 1:
return 1 # 明确的结束条件
return num + func(num - 1) # 每深一层,问题规模比上次少1
ret = func(100)
print(ret)
说明:
当num = 100时,可以看做(100+func(99)), func(99)又可以看做(99 + func(98)) ,当num=1时,返回1,又从后往前计算,当num=2时,2 + 1,依次类推,就能计算出100的和是多少
高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def getAbs(num):
return abs(num) # abs是一个求绝对值的函数
def add(num1, num2, func): # 高阶函数,接收getAbs函数为参数
return func(num1) + func(num2)
ret = add(3, -7, getAbs)
print(ret)