10 Python学习之函数

通过函数我们可以实现代码的重复利用,使代码简介,重复利用率高,

函数的定义

语法:

def 函数名(参数):

​ 函数体

​ 返回值

注意:

  1. def是关键字,不可省略
  2. 参数不是必须的,也可以无参
  3. 函数体可以有返回值,也可以没有
  4. 函数的调用是函数名 + 括号

例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的值已经改变了

运行结果:

调用前的全局变量:清华大学
修改全局变量:北京大学
调用后的全局变量:北京大学

递归函数

如果一个函数再内部调用自身,那么称这个函数为递归函数

递归的特性:

  1. 必须有一个明确的结束条件
  2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
  3. 递归效率不高,层次过多会导致栈溢出(在计算机中,函数调用时通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈机会减一层栈帧,由于栈的大小不是无限的,所以,递归调用次数过多,会导致栈溢出,大概在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)

posted @ 2020-07-14 21:56  爬坡的蜗牛  阅读(95)  评论(0编辑  收藏  举报