Day11 - 进阶函数

一、函数调用过程

1. 函数栈区间的声明周期
"""
每次调用函数的时候,系统会自动为这个函数创建一个临时的栈区间,用来保存在这个函数中产生的数据
当函数调用结束,这个栈区间会自动释放,里面保存的数据也会自动销毁
"""


def func1():
    a = 100         # a是保存在func1对应的临时栈区间中的


func1()
# print(a)      # NameError: name 'a' is not defined
# 函数调用结束的时候func1对应的临时栈区间会自动释放,数据全部销毁
2. return的作用
# 1)确定函数返回值  --  执行函数体的时候如果遇到return,return后面的值是函数返回值;没有遇到return返回值是None
# 2)提前结束函数  --  执行函数体的时候如果遇到return,函数提前结束


def func2():
    # return  --  直接结束函数,返回是None
    # return 100  --  返回一个返回值
    # return 100, 200  --  返回多个返回值
    for x in range(100):
        print('======')
        return
    print('end')


func2()
print(func2())

二、参数

1. 位置参数和关键字参数 – 根据实参提供方式的不同分类
"""
1)位置参数  --  调用函数的时候直接提供实参对应的数据,让实参和形参位置上一一对应
2)关键字参数  --  调用函数的时候在实参前面加'参数名=';关键字参数在使用的时候可以随意交换位置
3)位置参数和关键字参数混用:位置参数必须在关键字参数前面
"""


def func1(a, b, c):
    print(f'a:{a}, b:{b}, c:{c}')


# 位置参数
func1(10, 20, 30)       # a:10, b:20, c:30
func1(20, 10, 30)       # a:20, b:10, c:30

# 关键字参数
func1(a=10, b=20, c=30)     # a:10, b:20, c:30
func1(b=20, a=10, c=30)     # a:10, b:20, c:30

func1(10, b=20, c=30)
func1(100, c=300, b=200)
# func1(a=10, 20, c=30)
# SyntaxError: positional argument follows keyword argument


def func2(x, y):
    print(f'x:{x}, y:{y}')


func2(100, 200)     # x:100, y:200
2.参数默认值
"""
定义函数的时候可以以'形参=值'的方式给参数提供默认值
如果一个参数有默认值,那么调用函数的时候有默认值的参数可以不给传参

注意:如果定义函数的时候有的参数有默认值,有的参数没有,那么没有默认值的参数必须在有默认值参数的前面
"""


def func3(a=10, b=20, c=30):
    print(f'a:{a}, b:{b}, c:{c}')


func3()                     # a:10, b:20, c:30
func3(100)                  # a:100, b:20, c:30
func3(100, 200, 300)        # a:100, b:200, c:300
func3(a=100, b=200, c=300)  # a:100, b:200, c:300
func3(c=100)                # a:10, b:20, c:100

# SyntaxError: non-default argument follows default argument
# def func4(a=10, b, c=30):
#     print(f'a:{a}, b:{b}, c:{c}')


def func4(a, b=20, c=30):
    print(f'a:{a}, b:{b}, c:{c}')
3. 参数类型说明 – 定义函数的时候指定参数类型
"""
方法一:在没有默认值的参数后面加': 类型名'
方法二:给参数赋默认值,默认值是什么类型的数据,类型提示就是什么类型
"""


def func5(a: int, b: float, c: str):
    print(f'a:{a}, b:{b}, c:{c}')


func5(10, 2.5, 'abc')


def func6(str1: str, old, new: str, a=[]):
    new.join(str1.split(old))
4. (了解)不定长参数 – 参数个数不确定
"""
1)带*的不定长参数  --  在某个参数前面加*,那么这个参数就会变成一个不定长参数,调用的时候可以接受多个实参
带*的参数的本质就是一个元组,接收的所有的实参是这个元组中的元素

注意:给*的不定长参数传参的时候必须使用位置参数
记住:定义函数的时候如果参数列表中有*,*的作用是让*后面的参数在调用的时候必须使用关键字参数传参

2)带**的不定长参数
"""


# 定义一个函数,求多个数的和
def sum1(*nums):
    print(nums)


sum1()                      # ()
sum1(10)                    # (10,)
sum1(10, 20)                # (10, 20)
sum1(10, 20, 30, 40)        # (10, 20, 30, 40)


def func7(x, *y):
    print(x, end='')
    print(y)


func7(10)                           # 10()
func7(10, 20, 30, 40, 50, 60)       # 10(20, 30, 40, 50, 60)


# 注意:定长和不定长混用的时候,如果定长参数在*的后面,后面的参数必须全部使用关键字参数传参
def func8(x, *y, z):
    pass
    

func8(10, 20, 30, 40, 50, z=60)


# *后面的参数必须使用关键字参数传参
def func9(a, *, b, c):
    pass


func9(10, b=20, c=30)


def func10(**nums):
    print(nums)


func10()                    # {}
func10(a=10)                # {'a': 10}
func10(x=100, y=200)        # {'x': 100, 'y': 200}


def func11(*args, **kwargs):
    print(args, kwargs)


func11()            # () {}
func11(10)          # (10,) {}
func11(10, 20)          # (10, 20) {}
func11(a=11)            # () {'a': 11}
func11(10, 20, x=100, y=200)        # (10, 20) {'x': 100, 'y': 200}

三、匿名函数

"""
function 函数名(参数列表){
    函数体
}

def 函数名(参数列表):
    函数名
    
lambda 参数列表:返回值
"""
1. 匿名函数 – 没有名字的函数
"""
语法:
变量 = lambda 参数列表:返回值

def 函数名(参数列表):
    return 返回值 
"""
2. 匿名函数和普通函数的关系
# 除了定义的语法不一样,其他都一样(无参参数类型说明匿名函数不支持)
# 1)
a = lambda num1, num2: num1 + num2

# def a(num1, num2):
#     return num1 + num2

result = a(10, 20)
print(result)       # 30

# 2)
b = lambda x, y, z=30: print(f'x:{x}, y:{y}, z:{z}')

# def b(x, y, z=30):
#     return print(f'x:{x}, y:{y}, z:{z}')

b(10, 20, 30)               # x:10, y:20, z:30
b(x=100, z=300, y=200)      # x:100, y:200, z:300
b(100, 200)                 # x:100, y:200, z:30

# 3)
c = lambda x, *, y: x*y
result = c(10, y=20)
print(result)       # 200

# 练习1:定义一个匿名函数,获取指定正整数的十位数
get_tens_digit = lambda num1: num1 // 10 % 10
result = get_tens_digit(125)
print(result)       # 2

# 练习2:定义一个函数判断指定的年是否是闰年
is_leap_year = lambda year: (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
result = is_leap_year(2100)
print(result)       # False

四、实参高阶函数

1. 参数类型的确定
"""
函数的参数是什么样的数据由这个参数在函数中的使用来决定
比如,假如x是一个形参:
x + 10  ->  x必须是数字
x * 10  ->  x可以是数字,也可以是字符串、列表、元组
x[-1]  ->  x可以是字符串、列表、元组或者是有键为-1的字典
x.append(100)  ->  x必须是列表
...
x()  ->  x必须是函数,并且这个函数在调用的时候可以不用传参
x(10, 20)  ->  x必须是函数,并且这个函数在调用的时候可以接收两个传参
10 + x()  ->  x必须是函数,并且这个函数在调用的时候可以不用传参;返回值必须是数字
"""


def func1(x):
    # x()  --  函数调用表达式 -> x是函数,而且这个函数是可以不用传参
    x()


def a():
    print('这是一个函数')


func1(a)    # 这是一个函数
b = lambda item=10: item * 2
print(b())              # 20
print(func1(b))         # None
2. 如果参数是函数
# 如果一个函数的参数是函数,实参可以是普通函数的函数名,或者是匿名函数或者是保存匿名函数的变量来传参
def func2(x):
    # x=t; x=a
    x(10, 20)       # t(10, 20); a(10, 20)


def t(a, b):
    pass


a = lambda x, y: x+y
func2(t)
func2(a)
func2(lambda m, n: m*n)
3. 系统常用实参高阶函数:max/min/sored/列表.sort、map、reduce
# 实参高阶函数  --  如果函数的参数是函数,那么这个函数就是实参高阶函数
# 1)max/min/sored/列表.sort
"""
max基本用法:max(序列)  --  直接比较序列中元素的大小求最大值

max高级用法:max(序列, key=函数)  --  通过函数制定的比较规则来获取序列中元素的最大值
函数的要求:a. 是一个函数
           b. 有且只有一个参数,这个参数指向的是序列中每个的元素
           c. 有一个返回值,返回值就是真正的比较对象

"""
nums = [19, 82, 67, 34]

# 获取nums中值最大的元素
print(max(nums))        # 82

result = max(nums, key=lambda item: item)
print(f'result1:{result}')      # result1:82

# 练习:获取nums中个位数最大的元素 -> 19
nums = [19, 82, 67, 34]
result = max(nums, key=lambda item: item % 10)
print(f'result2:{result}')      # result2:19

# [82, 34, 67, 19]
nums.sort(key=lambda item: item % 10)
print(f'nums:{nums}')          # nums:[82, 34, 67, 19]

# 练习:获取nums中绝对值最大的元素 -> -340
nums = [19, 82, 67, -340]
result = max(nums, key=lambda item: item if item >= 0 else -item)
print(f'result3:{result}')      # result3:-340

# 练习:求students中年龄最大的学生
students = [
    {'name': 'stu1', 'age': 9, 'score': 90},
    {'name': 'stu2', 'age': 19, 'score': 66},
    {'name': 'stu3', 'age': 21, 'score': 72},
    {'name': 'stu4', 'age': 18, 'score': 89}
]
result = max(students, key=lambda student: student['age'])
print(f'result4:{result}')

result = sorted(students, key=lambda student: student['score'], reverse=True)
print(result)

# 练习: 获取nums中数值最大的元素  -> '34'
nums = [10, '34', 9.9, '5.5']
result = max(nums, key=lambda item: float(item))
print(f'result5:{result}')      # result5:34

# 练习:获取nums中各个位的和最大的元素
nums = [1000, 230, 97, 59, 101]


def temp(item):
    sum1 = 0
    for x in str(item):
        sum1 += int(x)
    return sum1


result = max(nums, key=temp)
print(f'result6:{result}')      # result6:97

result = max(nums, key=lambda item: sum([int(x) for x in str(item)]))
print(f'result6:{result}')      # result6:97
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值