python入门篇-day05-函数进阶

函数返回多个值

不管返回多少都会默认封装成一个元组的形式返回(可以自定义返回的数据类型 , 如: [ ]{ })

思考: 1个函数可以同时返回多个结果(返回值)?答案: 错误, 因为1个函数只能返回1个结果, 如果同时返回多个值则会封装成1个元素进行返回.

演示
# 需求: 定义函数 my_calculate(a, b), 返回两个整数的: 加减乘除结果.
def my_calculate(a, b):
    add = a + b
    sub = a - b
    mul = a * b
    div = a // b
    # return add, sub, mul, div   # 如果函数同时返回多个结果, 则会封装到1个元组中, 进行返回.
    return add, sub, mul, div   # 如果函数同时返回多个结果, 则会封装到1个元组中, 进行返回.
​
​
# 测试函数
if __name__ == '__main__':
    result = my_calculate(10, 3)
    print(type(result)) # <class 'tuple'>
    print(result)

函数的多种参数

函数参数指的是: 形参, 实参等一些特殊的写法.

书写位置: 普通参数 => 缺省参数 => 不定长参数

细节:

如果写实参的时候, 既有: 位置参数, 又有关键字参数, 则: 位置参数 必须在 关键字参数的前边. 但是关键字参数之间是没有顺序要求的, 随便写.

位置参数

要求:

实参 和 形参的 个数, 对应的顺序(位置) 都要相同.

演示
# 1. 定义函数, 打印信息.
def user_info(name, age, gender):  # 形参
    print(f'name: {name}, age: {age}, gender: {gender}')
​
​
# 2. 调用函数, 传递参数.
if __name__ == '__main__':
    # 位置参数 要求: 实参 和 形参 个数, 对应的顺序(位置) 都要相同.
    user_info('张三', 18, '男')  # 实参
    # user_info('张三', 18, '男', '北京')     # 报错, 实参 和 形参个数不同.
    user_info('张三', '男', 18)  # 不报错, 结果不是你要的.
    print('-' * 30)

关键字参数

要求

必须通过 形参名=值 的形式传递实参. 实参 和 形参的个数必须保持一致, 对顺序无要求.

演示
 # 关键字参数 要求: 实参 和 形参 个数要相同, 顺序无所谓.
    user_info(age=32, gender='男', name='乔峰')
    user_info(gender='男', age=32, name='乔峰')
    print('-' * 30)
​
    # 细节: 如果既有位置参数, 又有关键字参数, 则: 位置参数 必须在 关键字参数的前边.
    #          位置参数            关键字参数
    user_info('段誉', gender='男', age=23)
​
    # 报错.  位置参数在前, 关键字参数在后.
    # user_info(gender='男', '段誉', age=23)

缺省(默认)参数

概述

缺省参数也叫 默认参数, 它是作用于 形参列表的, 即: 可以给形参赋一个初始值, 这样用户调用函数的时候,如果没有给这个参数传参, 我们就用 默认值, 如果传参了, 就用给的值.

细节

形参列表中如果有 缺省参数, 则必须放 参数列表的最后.先这么记忆, 不严谨, 因为如果形参既有 普通参数, 又有 缺省参数, 还有 不定长参数,则顺序为: 普通参数 => 缺省参数 => 不定长参数

演示
# 1. 定义函数, user_info(), 用于打印信息.
def user_info(name, age, gender='男'):  # 缺省参数
    print(f'name: {name}, age: {age}, gender: {gender}')
​
​
# 2. 调用函数
if __name__ == '__main__':
    # 实参, 位置参数.
    user_info('张三', 30, '男')
​
    # 实参, 关键字参数
    user_info(name='张三', gender='男', age=30)
​
    # 实参, 位置参数 + 关键字参数
    user_info('阿朱', gender='女', age=25)
    print('-' * 30)
​
    # 测试: 缺省参数, 不传值.
    user_info('段誉', 25)
    # 测试: 缺省参数, 传值.
    user_info(age=23, name='小龙女', gender='女')

不定长参数

概述

它是作用于 形参列表的, 主要有两种写法, 分别是 *args: 可以接收任意多个位置参数, 并封装成: 元组. **kwargs: 可以接收任意多个关键字参数, 并封装成: 字典. keyword arguments

细节
  1. 不定长参数不是必须写成 *args, **kwargs,

    你写成 *a, *b, *c, **a都是可以的, 但是最好做到见名知意.

  2. *args, **kwargs 是不冲突的, 可以在形参中一起使用.

演示
# 需求1: 演示 不定长参数之  接收所有的 位置参数.
def user_info(*args):
    print(type(args))  # <class 'tuple'>
    print(args)  # ('张三', 23, '男')
​
​
# 需求2: 演示 不定长参数之  接收所有的 关键字参数.
def user_info2(**kwargs):
    print(type(kwargs))  # <class 'dict'>
    print(kwargs)  # {'name': '李四', 'age': 24, 'gender': '女'}
​
​
# 需求3: 演示 不定长参数之  接收所有的 位置参数和 关键字参数.
def user_info3(*args, **kwargs):   # 不定长参数
    print(f'args: {args}')      # (10, 20, 30)
    print(f'kwargs: {kwargs}')  # {'name': '李四', 'age': 24, 'gender': '女'}
​
# 需求4: 演示 普通参数 + 缺省参数 + 不定长参数之  接收所有的 位置参数和 关键字参数.
#             普通参数      缺省参数            不定长参数
def user_info4(a, b, c=10, d=20, e='AI30期', *args, **kwargs):   # 不定长参数
    print(f'a: {a}, b: {b}, c: {c}, d: {d}, e: {e}')
    print(f'args: {args}')      # (10, 20, 30)
    print(f'kwargs: {kwargs}')  # {'name': '李四', 'age': 24, 'gender': '女'}
​
​
​
# 测试上述的函数.
if __name__ == '__main__':
    # 传入 位置参数.
    user_info('张三', 23, '男')
    print('-' * 30)
​
    # 传入 关键字参数.
    user_info2(name='李四', age=24, gender='女')
    print('-' * 30)
​
    # 同时传入 位置参数 和 关键字参数
    #               位置参数             关键字参数
    user_info3(10, 20, 30, name='李四', age=24, gender='女')
    print('-' * 30)
​
    #                   位置参数                                      关键字参数
    user_info4(1, 2, 3, 4, 5, 6, 7, 8, 9, name='李四', age=24, gender='女')
    # 上行输出:a: 1, b: 2, c: 3, d: 4, e: 5
    #         args: (6, 7, 8, 9)
    #         kwargs: {'name': '李四', 'age': 24, 'gender': '女'}
    user_info4(1, 2, name='李四', age=24, gender='女')
    # 上行输出:  a: 1, b: 2, c: 10, d: 20, e: AI30期
    #           args: ()
    #           kwargs: {'name': '李四', 'age': 24, 'gender': '女'}

拆包

解释

组包: 把 多个值 => 1个值 的过程.拆包: 从 1个值 => 多个值 的过程.

细节
  1. 拆包针对于 元组, 列表, 字典, 集合, 字符串有效.

  2. 如果针对于 字典拆包, 则只能获取 的数据.

演示
# 1. 演示组包.      多个值 => 1个值
s1 = 'abcdef'
list1 = [1, 2, 3, 4, 5]
tuple1 = (1, 2, 3, 4, 5)
dict1 = {'a': 1, 'b': 2, 'c': 3}
set1 = {1, 2, 3, 4, 5}
​
# 2. 演示拆包.      1个值 => 多个值
# 演示字符串拆包.
# a, b, c, d = s1     # 报错, 变量的个数 和 字符串值的个数 不匹配.
a, b, c, d, e, f = s1
print(a, b, c, d, e, f)
print('-' * 30)
​
# 演示列表拆包.
a, b, c, d, e = list1
print(a, b, c, d, e)
print('-' * 30)
​
# 演示元组拆包.
a, b, c, d, e = tuple1
print(a, b, c, d, e)
print('-' * 30)
​
# 演示集合拆包.
a, b, c, d, e = set1
print(a, b, c, d, e)
print('-' * 30)
​
# 演示字典拆包.
a, b, c = dict1
print(a, b, c)  # 只能获取 键.

引用

可变和不可变图解

引用解释

概述

Python中存储变量是需要占用 内存空间的, 为了更好的管理这些空间, 每块空间都是有自己的地址值的.

格式

id(变量名 或者 变量值) 可以查看变量在内存中的 地址值.

细节

Python中的 = 是 引用传递, 即: 把等号右边的变量(值) 地址值 赋值个 左边的变量.

记忆
  1. 可变类型 和 不可变类型的划分依据:在不改变地址值的情况下, 其元素值是否可以发生改变, 可以 => 可变类型, 不可以 => 不可变类型.

  2. 可变 和 不可变类型划分如下:可变类型: 列表, 字典, 集合不可变类型: 整型, 浮点型, 布尔型, 字符串, 元组

演示
# 需求1: 观察如下的代码, 分析: 内存中到底有几个10.
a = 10
b = a
c = a
​
print(a, b, c)  # 10, 10, 10
​
# 观察 a, b, c的地址值.
print(id(a))    # 140726997170904
print(id(b))    # 140726997170904
print(id(c))    # 140726997170904
print('-' * 30)
​
# 需求2: 演示 不可变类型.    整型
a = 100
print(f'变量a的内容: {a}')       # 100
print(f'变量a的地址: {id(a)}')   # 0x01, 140727005431320
​
# 修改变量 a 的值.
a = 200
print(f'变量a的内容: {a}')       # 200
print(f'变量a的地址: {id(a)}')   # 0x02, 140727005434520
print('-' * 30)
​
# 需求3: 演示 可变类型.    列表.
list1 = [10, 20, 30]
print(f'变量list1的内容: {list1}')       # [10, 20, 30]
print(f'变量list1的地址: {id(list1)}')   # 0x01, 1676154425664
​
# 修改变量 list1 的值.
list1[1] = 200
print(f'变量list1的内容: {list1}')       # [10, 200, 30]
print(f'变量list1的地址: {id(list1)}')   # 0x01, 1676154425664

形参是可变或不可变对实参的影响

结论
  1. 形参是不可变类型, 则: 形参的改变对实参没有任何影响.

  2. 形参是可变类型, 则: 形参的改变 直接影响 实参.

形参的改变为函数内改变全局变量的实参
演示
# 需求1: 形参是 不可变类型.
def change(a):  # a: 形参
    a = 200
​
​
# 需求2: 形参是 可变类型.
def change2(list1):  # list1: 形参
    list1[1] = 200
​
​
# 测试上述的函数.
if __name__ == '__main__':
    # 测试需求1: 形参是 不可变类型.
    a = 100  # int类型, 不可变类型.
    print(f'调用 change 函数前, a = {a}')  # 100
    change(a)  # a: 实参, int类型(不可变类型)
    print(f'调用 change 函数后, a = {a}')  # 100
​
    # 测试需求2: 形参是 可变类型.
    list1 = [1, 2, 3]
    print(f'调用 change 函数前, list1 = {list1}')  # [1, 2, 3]
    change2(list1)  # list1: 实参, list类型(可变类型)
    print(f'调用 change 函数后, list1 = {list1}')  # [1, 200, 3]
形参是不可变类型

形参是可变类型

匿名函数lambda表达式

介绍

概述:

匿名函数指的是 没有名字的函数. 它类似于Java中的 lambda 表达式.

格式:

lambda 形参列表 : 函数体

细节:

匿名函数(也叫Lambda表达式, Lambda函数) 只适用于 简单的业务场景, 即: 函数体只有一行代码, 且有返回值的 这种函数.

应用场景:

匿名函数 可以作为方法的实参进行传递, 可以使得我们的代码更加简洁, 更加灵活.

演示
# 需求1: 求两个整数和.
# 思路1: 普通方式.
def get_sum(a, b):
    return a + b
​
​
# 需求2: 自定义函数 my_calculate(a, b, 功能), 分别计算两个整数的 加减乘除.
def my_calculate(a, b, func):
    """
    自定义函数, 模拟: 计算器, 基于传入的功能, 进行响应的操作.
    :param a: 要操作的第1个整数
    :param b: 要操作的第2个整数
    :param func: 具体的操作逻辑, 即: 函数对象.
    :return: 计算记过
    """
    return func(a, b)
​
​
# 在main函数中, 进行测试.
if __name__ == '__main__':
    # 1.测试自定义函数 get_sum()
    print(get_sum(10, 20))  # 30
​
    # 2.函数名 可以作为 对象传递.
    # sum = get_sum(10, 20)       # 这是在调用函数.
    func = get_sum  # 把 get_sum 这个函数对象 赋值给 变量func, 即: func() 和 get_sum()效果一致.
    print(func(10, 20))  # 30
​
    # 3.对上述的代码做变形, 使用匿名函数.
    my_sum = lambda a, b: a + b  # 它的效果, 等价于 get_sum()函数
    print(my_sum(10, 20))  # 30
    print('-' * 30)
​
    # 4. 匿名函数 作为方法的 实参进行传递.
    print(my_calculate(10, 3, get_sum))  # 求和, 13
    print(my_calculate(10, 3, lambda a, b: a + b))  # 求和, 13
    print(my_calculate(10, 3, lambda a, b: a - b))  # 求差: 7
    print(my_calculate(10, 3, lambda a, b: a * b))  # 求积: 30
    print(my_calculate(10, 3, lambda a, b: a // b)) # 求商: 3
    print(my_calculate(10, 3, lambda a, b: a % b))  # 取余: 3
    print(my_calculate(10, 3, lambda a, b: a ** b)) # 取平方: 1000
    print(my_calculate(10, 3, lambda a, b: max(a, b))) # 取最大值: 10
    print(my_calculate(10, 3, lambda a, b: a if a > b else b)) # 取最大值: 10

进阶案例

列表嵌套排序

# 又例如: sort(key=规则, reverse=True/False)函数, 对元素排序.
# 参1: key 接收的就是1个函数, 即: 排序规则.
# 参2: 是否翻转, True => 反转, 降序,   False => 不反转, 升序(默认)
#          5         6         7
list1 = ['apple', 'orange', 'bananas']
​
# 对 列表元素 排序, 默认排序规则: 字母的顺序, 升序排列.
# list1.sort()     # ['apple', 'bananas', 'orange']
​
# 对 列表元素 排序, 按照 字符串长度 升序排列
# list1.sort(key = lambda word : len(word))
​
# 对 列表元素 排序, 按照 字符串长度 降序排列
# list1.sort(key = lambda word : len(word), reverse=True)
​
# 对 列表元素 排序, 按照 字符串 第2个字母 进行排序.
list1.sort(key = lambda word : word[1])
​
# 打印排序后的内容.
print(list1)
print('-' * 30)

字符串字母排序

# 需求2: 对列表元素, 按照每个元素(元组形式) 的 第2个元素值 进行排序.
list1 = [(3, 2), (2, 5), (5, 1)]
​
# 默认: 按照元组的第1个元素值 进行排序.
# list1.sort()
​
# 按照每个元素(元组形式) 的 第2个元素值 进行排序.
# 方式1: 自定义函数, 实现排序规则.
# def sort_by_second(item):
#     return item[1]
#
# # 具体的排序动作.
# list1.sort(key=sort_by_second)
​
# 方式2: lambda函数实现.
list1.sort(key= lambda item : item[1])
# list1.sort(key= lambda item : item[1], reverse=True)
​
# 扩展: 按照元组的元素和排序.
# list1.sort(key= lambda item : sum(item), reverse=True)
# list1.sort(key= lambda item : item[0] + item[1], reverse=True)
​
print(list1)

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值