day11 函数的进阶

本文详细介绍了Python中的函数进阶特性,包括return的使用,函数的作用域(全局变量和局部变量),匿名函数(lambda)的定义与应用,以及实参高阶函数如max、min、sorted和map的用法。此外,还讲解了reduce函数的功能和迭代器的概念。
摘要由CSDN通过智能技术生成

day11 函数的进阶

一、return

return只能在函数体中使用

1. 返回值

将数据作为函数的返回值使用

return 数据

2. 结束函数

执行函数体的时候如果遇到return,函数直接结束。

def func1():
    print("+++++")
    print('------')


func1()


def func2():
    print('++++++')
    return 100  # 若return后不加数据表示到此结束函数体,返回值为None
    print('-----')  #  return后的不会使用


func2()   # ++++++  执行函数体的结果


print(func2())  # ++++++
                # 100  执行函数体并返回值
def func3(n):
    for x in range(1, n):
        if x % 3 == 0:
            return x
        print(f'x:{x}')


print(func3(5))

# x:1
# x:2
# 3
二、变量作用域

变量作用域:变量定义完之后使用的有效范围

根据变量作用域的不同,可以将变量分为全局变量和局部变量两种。

1. 全局变量

Pythonz中没有定义在函数中或者类中的变量默认都是全局变量(包括循环中定义的变量)

作用域:从定义开始到程序结束

a = 100  # a 是全局变量
for x in range(2):
    b = 200

print(b)
print(x)
# x 和 b 都是全局变量
2. 局部变量

定义在函数中的变量

作用域:从定义开始到函数结束

# m 和 n 是局部变量
def func2(m):
    n = 1000
    print(f'函数里面m:{m}')
    print(f'函数里面n:{n}')

func2(100)
# 函数里面m:100
# 函数里面n:1000

# print(f'函数外m:{m}')
# print(f'函数外n:{n}')   报错

补充:定义在类中的变量不是局部变量,而是属性,是不同于局部变量和全局变量的一个概念。

3. 全局变量和局部变量的存储原理

1)全局变量默认保存在全局栈区间,全局栈区间会在程序结束后自动释放

2)调用函数时系统会自动为这个函数创建一个临时栈区间,用来保持在函数中产生的数据
局部变量就是保存在函数对应的临时栈区间的,函数对应的临时栈区间会在函数调用结束时自动释放

3)在函数中可以通过关键字global修改局部变量的保存方式

  • 用global在函数内部定义全局变量

    def func1(m):  # m仍是局部变量
        global n  # 此时n是全局变量, 在函数外部也可以使用
        n = 100
        print(n)
    
    func1(100)
    print(n)
    
  • global在函数内部修改全局变量的值

name = '小明'
def fun2():
    global name
    name = '小花'

fun2()
print(name)  # 小花
三、匿名函数

函数名=lambda 形参列表:返回值

功能相当于:

def 函数名(形参列表):

​ return 返回值

注意

  1. 匿名函数形参至少一个(def 可以没有形参)

  2. 匿名函数的调用和普通函数一样

  3. 参数类型说明在匿名函数中不能使用

    # 案例:定义一个匿名函数,求任意两个数的和
    sum_2 = lambda num1, num2: num1+num2
    
    # 调用:
    result = sum_2(100, 200)
    print(result)  # 300
    
    # 练习:定义一个匿名函数,判断指定的年是否是闰年
    run_year = lambda year:(year % 4 == 0 and year % 100 !=0) or year % 400 == 0
    
    result = run_year(2020)
    print(result)
    
四、实参高阶

函数的参数是函数的函数就是实参高阶函数

给参数是函数的参数传参:a. 使用普通函数函数名 b. 使用匿名函数
重点:掌握系统或第三方库提供的实参高阶函数的用法
常见的实参高阶:max、min、sorted、列表.sort、map、reduce……

注意:在定义 函数中调用的函数时,形参个数要相对应。也要有返回值

# 此时func1就是一个实参高阶函数
def func1(x):
    x()

# func1()  # 此时这里传参应该传函数,普通函数和匿名函数都可以
# 观察发现传参的参数必须是没有参数的,因为func1中调用函数就是无形参的
def func3(x):
    print(x(10, 20) + 20)
# x(10,20)有两个形参,故传参的函数须得有两个形参
# x(10,20)为返回值,故参数需要有返回值


func3(lambda n1, n2: n1+n2)  # 50
五、常见的实参高阶函数
1. max
  • max(序列,key=函数名) — 普通函数

  • max(序列,key=函数) — 匿名函数

    max(序列,key=函数) — 按照函数制定的规则比较序列中元素的大小获取最大值
    函数要求:
    a. 有且只有一个参数(这个参数代表的是序列中的每个元素)
    b. 有一个返回值(返回值就是返回对象)

    若函数为普通函数,则key=函数名 即可,不用加括号。

    nums = [83, 67, 19, 22, 80, 77, 93]
    print(max(nums))
    

案例1:求个位数最大的元素

result = max(nums,key=lambda i: i%10)
print(result)
# 案例:求绝对值最大的元素
nums = [8, -283, 89, 100, 82, -34]
result1 = max(nums, key=lambda i: i ** 2)
print(result1)

# 案例:求分数最高的的学生
students = [
    {'name': 'stu1', 'age': 16, 'score': 90},
    {'name': 'stu2', 'age': 15, 'score': 96},
    {'name': 'stu3', 'age': 26, 'score': 60},
    {'name': 'stu4', 'age': 25, 'score': 45},
    {'name': 'stu5', 'age': 63, 'score': 83}
]
result2 = max(students, key=lambda i: i['score'])
print(result2)
2. min
# 练习2:求nums中十位数最小的元素
nums = [92, 129, 37, 99, 150, 501]
result2 = min(nums, key=lambda i: i//10)
print(result2)  # 37
3. sorted
# 练习3:将所有的学生按照年龄值从小到大排序
students = [
    {'name': 'stu1', 'age': 18, 'score': 90},
    {'name': 'stu2', 'age': 22, 'score': 98},
    {'name': 'stu3', 'age': 25, 'score': 78},
    {'name': 'stu4', 'age': 19, 'score': 81},
    {'name': 'stu5', 'age': 20, 'score': 92}
]
result3 = sorted(students, key=lambda i: i['age'])
print(result3)

练习4:求nums各个位数之和最大的元素

# 方法1:
nums = [123, 78, 90, 201, 192, 330]
result4 = max(nums, key=lambda i: sum(int(x) for x in str(i)))
print(result4)

# 练习4 方法2:
nums = [123, 78, 90, 201, 192, 330]
result5 = max(nums, key=lambda i: eval('+'.join(str(i))))
print(result5)


# 练习4 方法3: 用普通函数,参数仍然看作序列中的每一个元素
def sum_1(i):
    sum1 = 0
    for x in str(i):
        sum1 += int(x)
    return sum1


result = max(nums, key=sum_1)
print(result)
4. map

map — 基于一个或多个序列的元素产生一个新序列

map(函数,序列)

  • map(函数, 序列) — 通过函数描述的规则基于序列中的元素创建一个新的序列
    函数的要求:
    a. 有且只有一个参数(参数代表后面这个序列的每个元素)
    b. 有一个返回值(返回值就是新序列中元素)

  • map(函数, 序列1, 序列2) — 只用于最后结果产生过程是两个序列元素一一对应的才行
    函数要求:
    a. 有且只有两个参数(两个参数分别代表后面两个序列中的每个元素)
    b. 有一个返回值(返回值就是新序列中元素)

  • map(函数, 序列1, 序列2, 序列3……)

# 练习1:获取names中每个人的姓
names = ['何晓东', '张三', '李四', '王五', '王二', '赵六']
result = map(lambda i: i[0], names)
print(list(result))  # ['何', '张', '李', '王', '王', '赵']

# 练习2:
students = [
    {'name': 'stu1', 'age': 18, 'score': 90},
    {'name': 'stu2', 'age': 22, 'score': 98},
    {'name': 'stu3', 'age': 25, 'score': 78},
    {'name': 'stu4', 'age': 19, 'score': 81},
    {'name': 'stu5', 'age': 20, 'score': 92}
]
subjects = ['电子信息', '金融数学', '园林设计', '经济', '计算机软件']

# ['电子信息-stu1', '金融数学-stu2',....]

result1 = map(lambda i1, i2: '-'.join([i1, i2['name']]), subjects, students)
print(list(result1))
# '电子信息-stu1', '金融数学-stu2', '园林设计-stu3', '经济-stu4', '计算机软件-stu5']

# 方法:也可以不用join ,用  字符串拼接  或者  f'{i1}-{i2["name"]}'
5. reduce

reduce (函数,序列,初始值) — 按照函数规定的规则将序列中所有元素合并为一个数据。例如:

nums = [12, 301, 40, 55, 112]

把序列中所有数据 加起来、乘起来、个位数的和、合并为一个数据:123014055112 ……变成一个数据

函数的要求:
a. 有且只有两个参数(第一个参数指向初始值,第二个参数代表序列中每个元素)
b. 需要一个返回值(返回值就是合并规则)

初始值:具体看合并方式。
累计求数值和,初始值为0
累计乘积,初始值是1
字符串合并,初始值是空串

用reduce需要先导入: from functools import reduce

from functools import reduce

nums = [12, 301, 40, 55, 112]
# 案例1:把序列中所有数据 加起来
result = reduce(lambda x, i: x+i, nums, 0)
print(result)

# 案例2:把序列中所有数据 乘起来
result = reduce(lambda x, i: x*i, nums, 1)
print(result)

# 案例3:把序列中所有数据合并为一个数据:123014055112
result = reduce(lambda x, i: x+str(i), nums, '')
print(result)

# 案例4:求序列中所有数据的个位数的和
result = reduce(lambda x, i: x + i % 10, nums, 0)
print(result)
六、迭代器
1. 什么是迭代器(iter)
  1. 迭代器是容器型数据类型(可以遍历,也可以转换成列表), 无法直接提供一个迭代器,只能将其他序列转换成迭代器
    迭代器数据只出不进,用一个少一个。

  2. 特点:
    a. 打印迭代器时,无法查看元素有哪些
    b. 无法通过len获取迭代器中元素的个数
    c. 如果要使用迭代器中的元素,必须将元素从迭代器中取出来(取走),取走的元素会从迭代器中永远消失(用一个少一个)

  3. 任何数据都可以作为迭代器的元素

    # 1)创建迭代器
    i1 = iter('abc')
    i2 = iter([10, 20, 30])
    # 若将字典转换为迭代器,是去其键
    
    # 2)打印迭代器
    print(i1)  # <str_iterator object at 0x0000016A63920190>
    print(i2)  # <list_iterator object at 0x0000016A639201F0>
    
    # 3) 迭代器无法统计个数
    # print(len(i1)) --- 会报错
    
2. 获取迭代器中的元素

只支持查(增删改没有意义)

无论以任何方式获取到了迭代器的某个元素,那么这个元素就一定会从迭代器中消失
且获取的只能是当时迭代器最上面的那个元素

1)获取单个:
next(迭代器) – 获取迭代器最前面的元素

2)遍历迭代器
for 变量 in 迭代器: — 依次获取(取走)迭代器中的元素
循环体

print(next(i1))  # a
print(next(i1))  # b
print(next(i1))  # c
# print(next(i1))   #  此时迭代器是空的,所以会报错:StopIteration

print(next(i2))  # 10
print(list(i2))  # [20, 30]
# print(next(i2)) # 会报错,因为list(i2)以转换的方式已经取完了数据,寻找迭代器是空的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值