python语言基础(三)--公共方法、推导式和函数

一、公共运算符与方法

(一)公共运算符

概述:这些运算符是可以作用到容器类型中的

常见的运算符有:

常用的如下:
    +           合并(拼接), 适用于: 字符串, 列表, 元组.
    *           复制, 适用于: 字符串, 列表, 元组.
    in          是否包含, 适用于: 字符串, 列表, 元组, 字典.
    not in      是否不包含, 适用于: 字符串, 列表, 元组, 字典.
细节:
    in, not in 针对于字典的时候, 是只作用与 键的.

例如

# +           合并(拼接), 适用于: 字符串, 列表, 元组.
print('abc' + 'xyz')
print([1, 2, 3] + ['a', 'b', 'c'])
print((1, 2, 3) + ('a', 'b', 'c'))
print('-' * 30)

# *           复制, 适用于: 字符串, 列表, 元组.
print('abc' * 2)
print([1, 2, 3] * 2)
print((1, 2, 3) * 2)
print('-' * 30)

# in          是否包含, 适用于: 字符串, 列表, 元组, 字典.
print('a' in 'abc')             # True
print(10 in [1, 2, 3])          # False
print(10 in (10, 2, 3))         # True
print(10 in {10, 2, 3})         # True
print(10 in {1:2, 2:3, 10:5})   # True, 如果判断字典, 则判断的是: 键(key)
print(10 in {1:2, 2:3, 5:10})   # False, 如果判断字典, 则判断的是: 键(key)
print('-' * 30)

# not in      是否不包含, 适用于: 字符串, 列表, 元组, 字典.
print('a' not in 'abc')
print(10 not in [1, 2, 3])
print(10 not in (10, 2, 3))
print(10 not in {10, 2, 3})
print(10 not in {1:2, 2:3, 10:5})
print(10 not in {1:2, 2:3, 5:10})

(二)公共方法

概述:这些方法可以作用到容器类型中

常用方法

常用的如下:
   len()        获取长度的
   del          删除的
   max()        最大值
   min()        最小值
   range(start, end, step)      生成指定区间范围的值. 包左不包右.
   enumerate()  生成列表元素的: 索引 和 值, 封装成 元组形式, 即: (索引, 值)
细节:
    1. 如果len()统计字典, 统计的是: 键值对的对数.
    2. enumerate() 默认索引是从0开始的, 可以指定 起始索引.

例如

# 演示 len()        获取长度的
# 1. 字符串
s1 = 'abc'
print(len(s1))

# 2. 列表
print(len([1, 2, 3, 4, 5]))

# 3. 字典
print(len({'a': 1, 'b': 2, 'c': 3}))  # 3
print("-" * 30)

# 演示 del          删除的
# 1. 字符串.
s1 = 'abc'
del s1
# print(s1)

# 2. 列表
list1 = [1, 2, 3, 4, 5]
del list1[0]
del (list1[2])
print(list1)

# 3. 字典
dict1 = {'a': 1, 'b': 2, 'c': 3}
del dict1['a']
del (dict1['c'])
print(dict1)
print("-" * 30)

# 演示 max()        最大值
print(max('abcdefg'))
print(max([1, 2, 3, 4, 5]))
print(max((1, 2, 3, 4, 5)))
print(max({1, 2, 3, 4, 5}))
print(max({'a': 1, 'b': 2, 'c': 1}))    # 只针对于 键.
print("-" * 30)

# 演示 min()        最小值
# 同上, 自测.

# 演示 range(start, end, step)      生成指定区间范围的值. 包左不包右.
print(range(1, 10, 2))  # 生成 1 到 10 的 奇数, 获取: range()对象.
for i in range(1, 10, 2):
    print(i)

print(list(range(1, 10, 2)))    # 把 range() => 列表.
print("-" * 30)

# 演示 enumerate()  生成列表元素的: 索引 和 值.
list1 = ['a', 'b', 'c', 'd', 'e']

for i in list1:
    print(i)        # 'a', 'b', 'c', 'd', 'e', 它们的索引分别是: 0, 1, 2, 3, 4

# for i in enumerate(list1):    # 默认: 索引是从 0 开始的.
for i in enumerate(list1, 5):   # 指定 索引从 5 开始.
    print(i)        # 把列表元素和其索引封装成元组, 即: (索引, 值)
print('-' * 30)

# 扩展, 看看就行了, 把 列表 => 字典. 属于推导式,可以参照后文
dict1 = {item[0]:item[1] for item in enumerate(list1)}
print(dict1)

二、推导式

概述:推导式也叫解构式,即根据特定的规则生成1个数据序列的操作

分类:
    列表推导式:  [...]
    集合推导式:  {...}
    字典推导式:  {...}

细节:
    1. 有没有元组推导式呢? 即: (...).
        有, 但是不叫元组推导式, 叫: 生成器(Generator)
    2. 推导式支持 循环嵌套 以及 条件筛选的动作.

(一)列表推导式

格式

[变量名 for 变量名 in ... if 条件...]

例如

# 需求1: 创建0 ~ 9的列表.
# 思路1: 自定义 while 或者 for循环搞定.
list1 = []
for i in range(10):
    list1.append(i)
print(list1)

# 思路2: 列表推导式写法.
list2 = [i for i in range(10)]  # 效果同上.
print(list2)

print('-' * 30)


# 需求2: 创建1个0 ~ 9的 偶数列表.
# 方式1: 自定义 while 或者 for循环搞定.
list3 = []
for i in range(0, 10, 2):
    list3.append(i)
print(list3)

# 方式2: 列表推导式写法, 结合 步长.
list4 = [i for i in range(0, 10, 2)]
print(list4)

# 方式3: 列表推导式写法, 结合 if判断.
list5 = [i for i in range(10) if i % 2 == 0]
print(list5)

print('-' * 30)



# 需求3: 创建列表 => [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# 方式1: 分解版, 自定义for 或者 while循环搞定.
list6 = []
for i in range(1, 3):       # i的值: 1, 2
    for j in range(3):      # j的值: 0, 1, 2
        # 把元素添加到列表中.
        # my_tuple = (i, j)
        # list6.append(my_tuple)
        list6.append((i, j))
print(list6)

# 方式2: 列表推导式写法.
#                  外循环                内循环     =  外循环执行一次, 内循环指定一圈(一轮)
list7 = [(i, j) for i in range(1, 3) for j in range(3)]    # 效果同上.
print(list7)

如果读者不熟悉列表推导式,建议先写分解版的步骤,再写成推导式,等熟练后就可以一步写成了。

(二)集合推导式

格式

{变量名(键):变量名(值) for 变量名 in ... if 条件...}

例如

# 演示: 字典推导式
# 案例1: 创建1个字典, key是1~5, 值是这个数字的平方.
# 方式1: for, while 手动实现.
dict1 = {}
for i in range(1, 6):
    dict1[i] = i ** 2
print(dict1)

# 方式2: 字典推导式.
#         键值对
dict2 = {i : i ** 2 for i in range(1, 6)}
print(dict2)

print("-" * 30)


# 案例2: 将两个列表合并为1个字典.
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']

# 方式1: for, while手动实现.
dict3 = {}
for i in range(len(list1)):     # i的值: 0, 1, 2
    # i 就是 列表中的每个元素的 索引, 把索引对应的值 添加到 字典中即可.
    dict3[list1[i]]  = list2[i]
print(dict3)


# 方式2: 字典推导式.
dict4 = {list1[i] : list2[i] for i in range(len(list1))}    # i的值:0, 1, 2
print(dict4)
print("-" * 30)

(三)字典推导式

集合推导式 => 默认具有 元素去重的功能

格式

{变量名 for 变量名 in ... if 条件...}

例如

# 1. 定义1个列表, 记录一些元素.
list1 = [1, 1, 2]

# 2. 集合推导式实现, 获取的元素值为 上述元素的平方结果.
set2 = {i ** 2 for i in list1}     # i的值: 1, 1, 2
print(set2)     # {1, 4}    因为集合默认会: 去重. 

三、函数

(一)概述

函数也叫方法, 可以用单词 Function(函数, 功能), Method(方法) 来表示.
函数 = 把具有独立功能的代码封装到一起, 使其成为具有特殊功能的 代码集

好处是可以对一些重复性较高的代码进行封装复用,在日常工作中也是模块化编程,方便程序员开发项目。

函数的功能越单一越好, 最好1个函数只做1件事儿

(二)函数格式

定义格式:

    def 函数名(形式参数1, 形参2...):
        函数体, 就是以前写的逻辑代码, if, for...

        return 具体的返回值

    格式解释:
        def         defined单词的缩写, 表示: 定义1个函数.
        函数名      方便我们调用函数的, 起名时最好做到 见名知意.      get_max(), get_sum()
        形参参数     简称叫: 形参, 形容调用函数需要传入什么值.
        函数体      表示该函数要完成什么功能, 就是以前我们写的逻辑代码, if, for...
        return     作用1(主职): 结束函数的.   作用2(兼职): 可以返回函数的执行结果.

调用格式:

    1. 写 函数名()
    2. 传参.       这里写的是 实参(实际参数), 表示: 实际参与运算的数据.
    3. 接收返回值   如果有的话.

细节:

1、函数必须先定义, 然后才能调用.

2、函数只有被调用, 才会执行.

说明文档格式

# 函数内部用三引号,会自动识别参数和返回值,程序员需要对其注释,方便后期开发
def get_sum(a, b):
    """
    自定义函数, 用于计算 两个整数的 和
    :param a: 要求和计算的第1个整数
    :param b: 要求和计算的第2个整数
    :return: 返回a和b的 求和结果
    """
    sum = a + b
    return sum

(三)函数分类

1、根据参数和返回值分类

  1. 函数 根据 参数 和 返回值不同, 主要分为 如下的四种写法:
  • 无参无返回值.

  • 有参无返回值.

  • 无参有返回值.

  • 有参有返回值.

  1. 定义函数的时候, 写的参数列表叫: 形参, 形容调用函数, 需要传入什么值.

  2. 调用函数的时候, 写的参数列表叫: 实参, 表示调用函数时, 实际参与运算的数据.

  3. 函数只有被调用, 才会执行.

2、函数返回值

概述

返回值指的是 函数执行完毕后, 需要返回给 调用者一个什么样的结果

格式

在函数内部写, return 具体的返回值即可

例如

def get_sum(a, b):      # a, b 形参, 形容调用函数, 需要传入是什么样的值.
    """
    自定义函数, 计算两个整数的和.
    :param a: 求和运算的第1个整数
    :param b: 求和运算的第2个整数
    :return: 求和结果.
    """
    # 具体的求和过程
    sum = a + b
    # 返回求和结果
    return sum

3、四种函数展示

无参无返回值

def get_sum():
    sum = 10 + 20
    print(f'求和结果为: {sum}')
    return  # 方法的最后一行, 默认都有1个return, 表示结束方法, 并默认返回None

# 调用函数.
get_sum()

有参无返回值

def get_sum2(a, b):     # a,b充当的作色是 形参.
    """
    自定义函数, 用于计算两个整数和.
    :param a: 求合计计算用到的第 1个整数
    :param b: 求合计计算用到的第 2个整数
    :return: 空
    """
    sum = a + b
    print(f'求和结果为: {sum}')
    return  # 方法的最后一行, 默认都有1个return, 表示结束方法, 并默认返回None 打印求和结果.

# 调用函数.
get_sum2(1, 2)      # 1 和 2在这里充当的是: 实参(实际参数)
get_sum2(10, 20)    # 10 和 20在这里充当的是: 实参(实际参数)

无参有返回值

def give_list():
    """
    自定义函数,生成一个0到9的列表
    :return:[1, 2, 3..., 9]
    """
    return [i for i in range(10)] # 此处用列表推导式,非常方便

有参有返回值

def get_avg(a, b):
	"""
	自定义函数, 用于计算两个整数平均值.
    :param a: 求合计计算用到的第 1个整数
    :param b: 求合计计算用到的第 2个整数
    :return: 平均值
	"""
    return (a + b) // 2

(三)函数的嵌套调用

概述

函数的嵌套调用指的是 在一个函数中, 去调用另一个函数

流程

根据入栈的顺序, 进行执行的

例如

# 1. 定义 fun01 函数
def fun01():
    print('--- fun01 start ---')
    print('hello world!')
    print('--- fun01 end ---')

# 2. 定义 fun02 函数
def fun02():
    print('--- fun02 start ---')
    # 在 fun02()函数内, 调用 fun01()函数, 这就叫: 函数的嵌套调用.
    fun01()
    print('--- fun02 end ---')


# 3. 调用函数.
# fun01()
fun02()

(四)变量作用域

概述

变量的作用域指的是 变量的作用范围, 即: 变量在哪里能用, 在哪里不能用

分类

局部变量:

  • 定义到函数的形参列表, 或者 函数内的变量.
  • 只能在函数内部使用, 出了函数就用不了了.
  • 生命周期: 随着函数的调用而存在, 函数的调用完毕而消失.

全局变量:

  • 定义到函数外的变量, 或者 用 global 修饰的变量.
  • 在当前模块中的函数, 都可以使用.
  • 生命周期: 随着模块的加载而存在, 模块的卸载而消失.

global关键字介绍:
作用/概述:被它修饰的变量 => 全局变量, 可以实现, 定义 函数内的变量, 在函数外使用.

例如

# 需求1: 演示变量的生命周期 -> 局部变量.
def fun01():
    a = 10      # 局部变量
    print(f'函数内 a: {a}')


# 需求2: 演示变量的生命周期 -> 全局变量.
b = 30      # 全局变量
def fun02():
    global c            # 局部变量 => 全局变量
    c = 100             # 全局变量
    print(f'函数内 b: {b}')
    print(f'函数内 c: {c}')

# main函数, 程序的主入口.
if __name__ == '__main__':
    # 调用函数.
    fun01()

    # 函数外, 尝试调用 fun01()函数内的 局部变量 a
    # print(f'函数外 a: {a}')  报错, 超出了 局部变量的 生命周期.
    print('-' * 30)

    fun02()
    print(f'函数外 b: {b}')
    print(f'函数外 c: {c}')

(五)返回值

1、作为另一个函数的参数

注意

一个函数的返回结果, 可以作为另一个函数的参数

例如

# 1. 定义函数, 返回1个整数.
def get_number():
    return 30


# 2. 定义函数, 传入1个整数, 判断其奇偶性.
def is_odd(n):
    if n % 2 == 0:
        print(f'{n} 是偶数!')
    else:
        print(f'{n} 是奇数!')


# 3. 测试上述的函数.
if __name__ == '__main__':
    # 分解版写法
    # 3.1 获取整数
    n = get_number()        # n = 30

    # 3.2 把 n(1个函数的返回值)  作为 is_odd()函数的参数进行传递.
    is_odd(10)
    is_odd(11)
    is_odd(n)
    print('-' * 30)

    # 合并版.
    is_odd(get_number())        # 细节: 函数的返回值, 可以作为另一个函数的参数.
    print('-' * 30)

2、返回多个结果(以元组形式)

注意

函数返回多个结果: 会把多个结果 封装成1个元组进行返回

例如

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)) # 
    print(result)

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

(六)参数

概述

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

分类

位置参数:
关键字参数:
缺省参数:
不定长参数:
    *args
    **kwargs

1、位置参数

要求

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

例如

def user_info(name, age, gender):  # 形参
    print(f'name: {name}, age: {age}, gender: {gender}')
    
if __name__ == '__main__':
    # 位置参数 要求: 实参 和 形参 个数, 对应的顺序(位置) 都要相同.
    user_info('张三', 18, '男')  # 实参
    # user_info('张三', 18, '男', '北京')     # 报错, 实参 和 形参个数不同.
    user_info('张三', '男', 18)  # 不报错, 结果不是你要的.

2、关键字参数

要求

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

细节

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

例如

def user_info(name, age, gender):  # 形参
    print(f'name: {name}, age: {age}, gender: {gender}')
    
if __name__ == '__main__':
    # 关键字参数 要求: 实参 和 形参 个数要相同, 顺序无所谓.
    user_info(age=32, gender='男', name='乔峰')
    user_info(gender='男', age=32, name='乔峰')
    print('-' * 30)

    # 细节: 如果既有位置参数, 又有关键字参数, 则: 位置参数 必须在 关键字参数的前边.
    #          位置参数            关键字参数
    user_info('段誉', gender='男', age=23)

    # 报错.  位置参数在前, 关键字参数在后.
    # user_info(gender='男', '段誉', age=23)

3、缺省参数

概述

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

细节

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

例如

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='女')

4、不定长参数

概述

它是作用于 形参列表的, 主要有两种写法, 分别是

  • *args: 可以接收任意多个位置参数, 并封装成: 元组.
  • **kwargs: 可以接收 任意多个关键字参数, 并封装成: 字典. keyword arguments

细节

不定长参数不是必须写成 *args, **kwargs, 你写成 *a, *b, *c都是可以的, 但是最好做到见名知意.

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

例如

# 需求1: 演示 不定长参数之  接收所有的 位置参数.
def user_info(*args):
    print(type(args))  # 
    print(args)  # ('张三', 23, '男')


# 需求2: 演示 不定长参数之  接收所有的 关键字参数.
def user_info2(**kwargs):
    print(type(kwargs))  # 
    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='女')
    user_info4(1, 2, name='李四', age=24, gender='女')

(七)形参是可变和不可变对实参的影响

在开始之前,我们需要先讨论一下python中的引用概念.

1、引用

概述

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

2、形参是可变类型时

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

例如

def change(list1):  # list1: 形参
    list1[1] = 200
    
if __name__ == '__main__':
    # 形参是 可变类型.
    list1 = [1, 2, 3]
    print(f'调用 change 函数前, list1 = {list1}')    # [1, 2, 3]
    change(list1)   # list1: 实参, list类型(可变类型)
    print(f'调用 change 函数后, list1 = {list1}')    # [1, 200, 3]

当形参时可变类型时,列表将自己的地址传给函数,函数指到地址位置,然后修改内部值,因为时可变类型,所以不需要另外开辟地址,直接在原地址的空间上修改值,当函数结束时,直接出栈,断开连向变量地址的指针,但是此时地址内的变量值已经改变,所以后面再读取时,值已经改变.

3、形参是不可变类型时

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

例如

def change(a):    # a: 形参
    a = 200
   
if __name__ == '__main__':
    # 形参是 不可变类型.
    a = 100  # int类型, 不可变类型.
    print(f'调用 change 函数前, a = {a}')    # 100
    change(a)     # a: 实参, int类型(不可变类型)
    print(f'调用 change 函数后, a = {a}')    # 100

当形参是不可变类型时,列表将自己的地址传给函数,函数指到地址位置,此时函数想要改变变量的值,但是由于参数时不可变类型,所以为新值在内存中开辟一块新的地址,变量指向新空间地址,此时函数完成,做出栈操作,变量指向新地址的操作会因此断开,到了main函数处,实参会重新指向(或者说根本没有改变过)原来的地址,因此值不会发生改变。

(八)匿名函数

1、入门

概述

匿名函数指的是 没有名字的函数. 它类似于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

2、进阶

概述

实际开发中, Python中的很多函数, 为了实现满足用户灵活多变的需求, 会引入匿名函数, 使得代码变得更加的灵活

例如

此处用自带的sort()函数做例子,来展示匿名函数的灵活性.

利用匿名函数来自定义依据什么来对元素进行排序.

# 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)

(九)拓展–组包与拆包

概述

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

细节

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

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

例如

# 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语法,python,开发语言)