13.函数参数和返回值&函数封装&匿名函数

一、函数基本使用

1.参数

1.1参数分类

形式参数:简称形参,定义在函数的声明部分,本质是一个没有值的变量,用于接收实参的值

实际参数:简称实参,出现在函数的调用过程中,本质是一个有值的变量或者常量,用于给形参赋值

传参:实参给形参赋值的过程

参数分类:

  • 必需参数

  • 默认参数

  • 关键字参数

  • 不定长参数【可变参数】

基本使用

# 1.必需参数,常用
# 注意1:如果形参是必需参数,调用函数的时候,实参和形参的数量必须保持一致
def func1(a,b):
    print(a + b)
# func1(23)  # TypeError: func1() missing 1 required positional argument: 'b'
func1(23,5)
# 注意2:如果形参是必需参数,根据函数的具体实现需求,实参需要注意类型的问题
# func1(34,'abc')  # TypeError: unsupported operand type(s) for +: 'int' and 'str'
func1('hello','python')
​
# 2.默认参数
# 注意1:默认参数体现在形参中,实参可以不用给默认参数传参,也可以给默认参数传参,会覆盖掉默认值
# a.练习:封装一个函数,计算任意一个数和5的和
# 使用必需参数的方式封装,缺点:繁琐
def add(num1,num2):
    print(num1 + num2)
add(10,5)
add(23,5)
add(30,5)
​
# 使用默认参数进行优化
# 注意2:默认参数的出现,可以简化函数的调用
def add(num1,num2=5):
    print(num1 + num2)
add(10)
add(23)
add(30)
​
add(10,20)
​
# b.默认参数的体现:int(value,base)
print(int('110'))
print(int('101'))
​
print(int('110',10))
print(int('101',10))
​
print(int('110',2))
print(int('101',2))
# 练习
def add(num1=0,num2=0):
    print(f"{num1} + {num2} = {num1 + num2}")
add()
add(34)
add(23,9)
​
# 3.关键字参数
# 注意1:关键字参数体现在函数的调用部分,通过关键字参数传参,可以调换参数的顺序
# 注意2:调用函数的时候,如果使用关键字参数,则关键字一定要和形参名称保持一致
def func31(name,age):
    print(f"姓名:{name},年龄:{age}")
func31('张三',10)
func31(name='李四',age=20)
# func31(23,'jack')   # 姓名:23,年龄:jack
func31(age=23,name='jack')
​
# 练习1
def add(num1=0,num2=0):
    print(f"{num1} + {num2} = {num1 + num2}")
add()
add(34)
add(23,9)
add(num2=66)
​
# 练习2:
# 注意3:传参过程中,只要保证形参都有值
def func32(name,age=0):
    print(f"姓名:{name},年龄:{age}")
func32('aaa')
func32('aaa',34)
func32(name='aaa')
func32(name='aaa',age=6)
func32(age=8,name='aaa')
​
# 关键字参数在系统函数中体现较多
print(34,45,5,5,sep='*')   # 同时体现了默认参数和关键字参数
print(int('110',base=2))
​
# 4.不定长参数/可变参数
# a. *x:x将会被当做元组处理,实参可以是任意数量的数据
def func41(*num):    # 打包
    print(num,type(num))
    print("*num:",*num)  # 拆包
​
func41()    # () <class 'tuple'>
func41('abc')  # ('abc',) <class 'tuple'>
func41('abc',45,65,7,8,89,9,True)  # ('abc', 45, 65, 7, 8, 89, 9, True) <class 'tuple'>
​
# b.**x:x将会被当做字典处理,实参必须以key=value的方式传参,key必须是一个标识符
def func42(**num):   # 打包
    print(num,type(num))
func42()
func42(x=45,y=6,z=67)  # {'x': 45, 'y': 6, 'z': 67}
func42(abc='hello')
​
dict1 = {'a':10,"b":20}
func42(**dict1)   # 拆包
​
# 说明:在实际应用中,*和**可以同时使用
def func(*args,**kwargs):
    print(args,kwargs)
func()
func(10,20)
func(10,20,name='zhangsan',age=10)

详细使用

# 1.必需参数
# a.注意1:必需参数传参的时候,一定要注意数量的匹配
def func1():
    print("func~~~1111")
func1()
# func1(34)   # TypeError: func1() takes 0 positional arguments but 1 was given
​
# b
def func2(a):
    print("func~~~222",a)
# func2()       # TypeError: func2() missing 1 required positional argument: 'a'
func2(10)
func2("abc")
​
# c.注意2:必需参数传参的时候,一定要注意顺序的匹配
def func3(name,age):
    print(f"姓名:{name},年龄:{age}")
# func3(18,"jack")
func3("jack",18)
​
# d.注意3:必需参数传参的时候,一定要注意类型的匹配
def func4(name,age):
    print("姓名:%s,年龄:%d" % (name,age))
# func4("aaa","gahjg")  # TypeError: %d format: a number is required, not str
func4("张三",10)
​
print("*" * 30)
​
​
# 2.默认参数
# a.注意1:默认参数体现在形参上
def test1(a,b = 0):   # a是一个必需参数,b是一个默认参数
    print(a,b,a + b)
# 注意2:形参使用默认参数,如果实参给该参数未传参,则使用默认值
test1(3)
test1(3,5)    # 5会给b重新赋值
​
​
# b.
def test2(a = 0,b = 0,c = 0):
    print(a,b,c)
test2()
test2(2,6)
test2(3,4,6)
​
def test3(a,b = 0,c = 0):
    print(a,b,c)
test3(6)
​
def test4(a,b,c = 0):
    print(a,b,c)
test4(6,3)
​
# 注意3:如果形参有多个,可以必需参数和默认参数混合使用,但是在形参中,默认参数靠后书写
# def test4(a,b = 0,c):   # SyntaxError: non-default argument follows default argument
#     print(a,b,c)
# test4(6,3)
​
# 注意4:默认参数出现的意义就是为了简化函数的调用
# end默认值为\n
print(45)
print(60)
# print(34,end="*")
​
​
# 3.关键字参数
# 注意1:关键字参数体现在实参中
def check1(name,age,score):
    print(f"姓名:{name},年龄:{age},成绩:{score}")
# check1("jack",18,100)
# check1(18,"jack",100)  # 逻辑不通,姓名:18,年龄:jack,成绩:100
​
# 注意2:使用关键字参数传参可以不用匹配顺序,但是,关键字需要和形参的变量名保持一致
check1(age=18,name="jack",score=100)  # 姓名:jack,年龄:18,成绩:100
# check1(age=18,name1="jack",score=100)  # TypeError: check1() got an unexpected keyword argument 'name1'
check1('aaa',score=88,age=10)
check1("bbb",12,score=99)
​
# 注意3:在实参中,关键字参数只能书写在参数的后面
def check2(name,age,score):
    print(f"姓名:{name},年龄:{age},成绩:{score}")
# check2(name="tom",10,66)  # SyntaxError: positional argument follows keyword argument
# check2(10,66,name="tom")  # TypeError: check2() got multiple重复 values for argument 'name'
​
# 注意4:默认参数和关键字参数可以结合使用
def check3(name,age,score=0):
    print(f"姓名:{name},年龄:{age},成绩:{score}")
check3("jack",10)
check3("jack",10,67)
check3(name="jack",age=10,score=67)
check3("jack",age=10,score=67)
check3("jack",10,score=67)
​
print("*" * 30)
​
​
# 4.不定长参数/可变参数:可以接受不定长的参数
# a.*xxx,
# 注意1:*xxx,xxx被当成一个元组处理
def text1(*num):
    print(num)
text1()
text1(34)
text1(34,56,67,68,7,8)
text1(34,56,67,68,7,8,"abnfa",True)
​
# 注意2:必需参数可以和不定长参数混合使用
def text2(num1,*num2):
    print(num1,num2)
text2(10,45,56,67,6,8,7,8)
​
# 注意3:如果不定长参数出现在形参列表的前面,则可以结合关键字参数完成传参
def text3(*num1,num2):
    print(num1,num2)
# text3(10,45,56,67,6,8,7,8)  # TypeError: text3() missing 1 required keyword-only argument: 'num2'
text3(10,45,56,67,6,8,7,num2 = 8)
​
​
# 注意4:*xxx在形参列表中只能被使用一次
# def text4(*num1,*num2):
#     print(num1,num2)
# text4(45,57,6,77,8)
​
print("*" * 30)
​
# b.**xxx
# 注意1:**xxx,xxx会被当做字典处理
def f1(**num):
    print(num)
​
# 注意2:给**xxx的形参传参,则必须以key=value的方式传参
f1(x=10,y=20,z=30)  # {'x': 10, 'y': 20, 'z': 30}
​
# 注意3:**xxx在同一个函数的形参中只能出现一次
# def f2(**num1,**num2):
#     print(num1)
# f2(x=10,y=20,z=30)
​
# 注意4:*xxx和**xxx可以同时使用,但是,分别只能使用一次
def f3(*num1,**num2):
    print(num1,num2)
f3(45,45,65,7,67)
f3(45,45,65,7,67,a=4,b=467,fag="abc")
f3(a=4,b=467,fag="abc")
​
# 注意5:一般情况下,如果*xx和**xxx结合使用,命名为:*args,**kwargs

1.2参数传递

# 参数的传递:值传递和引用传递
​
"""
简述值传递和引用传递的区别
值传递:传参的时候,传递的是不可变的数据类型,如:int/float/str/tuple/bool,当形参发生修改,对实参没有影响
引用传递:传参的时候,传递的是可变的数据类型,如:list/dict/set等,当形参中的元素发生修改,则实参会随着修改
"""
​
# 1.值传递
def func1(num):
    print(f"修改之前,num的地址:{id(num)}")
    num = 100
    print(f"修改之后,num的地址:{id(num)}~~~~")
​
temp = 45
func1(temp)
print(f"temp的值:{temp}")
​
​
print("*" * 50)
​
​
# 2.引用传递
def func1(num):
    print(f"修改之前,num的地址:{id(num)}")
    num[1] = 100
    print(f"修改之后,num的地址:{id(num)}~~~~")
​
temp = [2,3,4]
func1(temp)
print(f"temp的值:{temp}")

2.返回值

# 1.return
# 注意1:return是一个关键字,可以单独作为一条语句,只能使用在函数中,表示结束函数
# 注意2:同级的情况,在return的后面不添加任何语句,否则永远没有执行的机会
# a
def show1():
    print('1111')
    return
    print('over')
show1()
​
# b
# 注意3:不同级的情况下,只要return有可能执行不到,return的后面是可以添加语句的
def show1(a):
    print('1111')
    if a > 10:
        return
    print('over')
show1(20)
​
# c.return和break
"""
return:使用在函数中,表示结束函数,不管return处于多少层循环中,只要执行到return,函数都会结束
break:使用在循环中,表示结束当前循环
"""
def func1():
    print('start')
    for i in range(3):
        for j in range(5):
            print(f"{i}={j}")
            if j == 2:
                break
    print("end")
func1()
​
print("*" * 50)
​
def func2():
    print('start')
    for i in range(3):
        for j in range(5):
            print(f"{i}={j}")
            if j == 2:
                return
    print("end")
func2()
​
print("*" * 50)
​
# 2.return  xxx:此处的return不但表示结束函数,还表示在函数调用的过程中将指定值返回
# 注意1:如果函数没有设置返回值,则函数调用完毕之后,默认返回None
# 注意2:函数调用完毕之后,可以使用一个变量将返回值接出来
def show21():
    print('222222')
r1 = show21()   # r1 = 返回值
print(r1)
​
# 注意3:如果一个函数设置了返回值,则函数在哪里调用,返回值会返回值到哪里
def show22():
    print('222~~~~~')
    return 66
r2 = show22()
print(r2)
print(show22())   # 如果一个函数的调用可以直接通过print打印,则说明该函数有返回值
​
def show23():
    return 'abc',10,45
print(show23())  # ('abc', 10, 45)
​
# 3.给函数设置返回值的意义
def add1(num1,num2):
    # 局部变量
    total = num1 + num2
    print(total)
add1(23,10)
# print(total)    # NameError: name 'total' is not defined
​
def add2(num1,num2):
    total = num1 + num2
    return total
r = add2(34,18)
print(r)
​
# list1 = [34,56,6]
# list1.append(34)
# print(list1)

3.函数的封装

"""
def xxx(形参):
    函数体【要实现的需求】
    return 返回值
​
如果要封装一个函数,需要注意两个方面:
    是否需要设置形参:如果需求中有未知项参与运算,则设置为形参
    是否需要设置返回值:如果需求运算完是否有结果,如果有结果,则设置返回值
"""
​
# 1.封装函数,比较两个数的大小,返回较大的值
def compare1(num1,num2):
    if num1 > num2:
        return num1
    return num2
r = compare1(34,10)
print(r)
def compare2(num1,num2):
    if num1 > num2:
        return num1
    elif num1 < num2:
        return num2
    else:
        return "相等"
r = compare2(10,10)
print(r)
​
# 2.封装函数,判断一个年份是否是闰年
def isleapyear(year):
    # if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
    #     return True
    # return False
​
    return year % 4 == 0 and year % 100 != 0 or year % 400 == 0
​
r = isleapyear(2021)
print(r)
​
# 3.验证指定数是否是质数
def isprime(num):
    if num < 2:
        return False
    else:
        result = True
        for n in range(2, num):
            if num % n == 0:
                result = False
                break
        return result
r = isprime(11)
print(r)

4.匿名函数

概念:不再使用def这种标准形式定义函数,而是使用lambda表达式来创建函数,该函数没有函数名,被称为匿名函数,匿名函数也被称为lambda表达式

语法:lambda 形参列表:返回值

说明:

​ a.lambda只是一个表达式,用一行代码实现一个简单的逻辑,可以达到对函数的简化【优点】

​ b.lambda主体是一个表达式,而不是一个代码块,只能封装有限的逻辑【缺点】

​ c.lambda拥有自己的命名空间,不能访问自有列表之外或者全局命名空间里的参数

# 语法:lambda  形参列表: 返回值
​
# 1.
# a.def标准函数
# 定义
def func1():
    print('111')
print(func1)   # <function func1 at 0x106778f70>
# 调用
r1 = func1()
print(r1)
​
# b.匿名函数
# 定义
# lambda :print('111!~~~~')
f2 = lambda :print('111!~~~~')
print(f2)   # <function <lambda> at 0x106814790>
​
# 调用
# 方式一:变量  = lambda xx:xxx,通过该变量就可以调用函数
r2 = f2()
print(r2)
​
# 方式二:不常用
# (lambda :print('111!~~~~'))()
​
# 2.
def add1(num1,num2):
    return num1 + num2
r1 = add1(34,5)
print(r1)
​
# 注意:匿名函数的返回值不需要return
add2 = lambda num1,num2:num1 + num2
r2 = add2(23,9)
print(r2)
​
# 3.
def even1(num):
    if num % 2 == 0:
        return True
    return False
r1 = even1(10)
print(r1)
​
even2 = lambda num:True if num % 2 == 0 else False
r2 = even2(35)
print(r2)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiayi_init_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值