python函数的高阶使用

一:* 强制位置传参和 / 分界线

  1. 强制位置参数可以使用*进行标记,*后面的参数将成为强制位置参数,它们必须按照位置传递给函数,而不能使用关键字传递。
  2. / 用于标记位置参数和关键字参数之间的分界线,即 / 之前的参数只能通过位置传递,/ 之后的参数可以通过位置或关键字传递。
  • 示例1:使用*强制位置传参
def f(a,b,*,c):
    return a+b+c

f(1,2,3)   # 报错 TypeError
f(1,2,c=3) # 正常 6
  • 示例2:使用/关键字传参,/ 之前的参数只能通过位置传递,/ 之后的参数可以通过位置或关键字传递。
def foo(a, b, /, c, d):
   print(a, b, c, d)

foo(1, 2, 3, 4)  # 输出:1 2 3 4
foo(1, 2, c=3, d=4)  # 正确的调用方式,c和d可以通过关键字传递
foo(1, 2, 3, d=4)  # 正确的调用方式,c通过位置传递,d通过关键字传递
foo(a=1, b=2, c=3, d=4)  # 错误的调用方式,a、b只能位置传参

二、函数递归

函数的递归是指在函数内部调用自身的过程。通过递归,函数可以重复执行相同的操作,每次处理一个更小或更简单的子问题,直到达到终止条件。递归的本质是一个灵活的循环。
 
要使用递归函数,通常需要满足两个条件:
  1. 定义递归终止条件:确定在什么情况下递归应该停止,避免无限递归。
  2. 在递归调用中处理更小或更简单的子问题:将原问题分解为一个或多个更小的子问题,并通过递归调用处理这些子问题。
  • 递归函数的基本结构如下:
复制代码
def recursive_function(arguments):
    # 检查递归终止条件
    if base_case:
        return base_value
    
    # 处理更小或更简单的子问题,并通过递归调用解决
    smaller_problem = simplify_problem(arguments)
    result = recursive_function(smaller_problem)
    
    # 对子问题的结果进行处理,并返回最终结果
    final_result = process_result(result)
    return final_result
复制代码
  • 以下是一个计算阶乘的递归函数的示例:
复制代码
def factorial(n):
    # 递归终止条件:n等于0或1时,阶乘为1
    if n == 0 or n == 1:
        return 1
    # 递归调用:计算(n-1)的阶乘,并乘以n
    return n * factorial(n - 1)

# 测试代码
n = 5
result = factorial(n)
print(f"The factorial of {n} is: {result}")# 运行结果 The factorial of 5 is: 120
复制代码
  • 在上面的例子中,factorial函数计算给定数 n 的阶乘。当 n 的值等于0或1时,递归终止,返回1。否则,递归调用factorial函数来计算 (n-1) 的阶乘,并将结果乘以 n。通过递归调用,问题的规模逐渐减小,直到达到终止条件。
  • 注意事项:
  1. 确保存在递归终止条件:递归函数必须能够在某个条件下停止递归,否则会导致无限递归,耗尽计算资源并导致程序崩溃。
  2. 保证每次递归调用问题规模的缩小:递归函数应该通过每次递归调用处理更小或更简单的子问题,以确保问题规模逐步减小,最终达到终止条件。
  3. 控制递归的层数:递归函数的层数过多可能导致栈溢出(Stack Overflow),限制了递归的使用范围。
  4. 注意递归函数的性能:递归函数可能在处理大规模问题时具有较高的时间和空间复杂度,需要谨慎使用,可以考虑使用迭代等其他方式进行优化。
  5. 递归函数在解决问题时常见的例子包括计算阶乘、斐波那契数列、遍历树等。使用递归时,要确保递归终止条件正确设置,并小心处理递归调用中的问题规模和递归层数,以避免潜在的问题

三、常用内置函数

  1. enumerate()函数

  • enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
  • 语法:enumerate(iterable, start=0)
    • iterable: 可迭代对象,如列表、元组、字符串、字典等。
    • start: 可选参数,指定起始的索引,默认为 0。
fruits = ['apple', 'banana', 'orange']

for index, fruit in enumerate(fruits):
    print(index, fruit)
# 输出结果
# 0 apple
# 1 banana
# 2 orange
  • 使用 enumerate() 函数时需要注意以下几点:
    • enumerate() 返回的是一个迭代器,可以通过 list() 函数将其转换为列表。
    • 可以通过指定 start 参数来指定起始的索引,默认为 0。
    • enumerate() 函数常用于需要同时获取索引和元素的情况,如遍历列表时需要知道当前元素的位置。
    • 在使用 enumerate() 函数时,注意迭代对象的顺序和索引的对应关系。

  2. eval()函数

  • eval() 函数用来执行一个字符串表达式,并返回表达式的值。也可以将字符串还原成原本的数据类型
  • 语法:eval(expression, globals=None, locals=None)
    •   expression:需要求值的字符串表达式。
    •   globals:可选参数,全局命名空间,
    •   locals:可选参数,局部命名空间,如果被提供,可以是任何映射对象
复制代码
x = 5
result = eval('x * 2')
print(result)# 输出结果10

d = '{"name":"test","age":18}'
print(eval(d)) # 得到一个字典

l = '[1,2,3,4,5]'
print(eval(l))  # 得到一个列表
复制代码
  • 在使用 eval() 函数时需要注意以下几点:
    •   谨慎使用 eval() 函数,因为它可以执行任意的表达式,可能存在安全风险。
    •   只有在信任输入内容并且确保安全性的情况下,才应该使用 eval() 函数。
    •   在使用 eval() 函数时,需要注意表达式的语法正确性,否则会引发 SyntaxError 异常

  3. zip()函数

  • zip() 函数用于将多个可迭代对象(例如列表、元组或字符串)进行压缩,返回一个由元组组成的
  • 语法:zip(*iterables)
    • iterables 是一个或多个可迭代对象,可以是列表、元组、字符串或其他可迭代对象
x = [1, 2, 3]
y = [4, 5]

zipped = zip(x, y)  
print(list(zipped))
# 输出结果 [(1, 4), (2, 5)]
  • 以下是一些使用 zip() 函数的注意事项:
    • 当传入的可迭代对象长度不一致时,zip() 函数返回的迭代器长度为最短的可迭代对象的长度。
    • 如果需要获取完整的压缩结果,可以使用 list() 函数将迭代器转换为列表。
    • 当传入空的可迭代对象时,zip() 函数不会产生任何输出。
    • 如果需要同时迭代多个可迭代对象,并且需要对应的元素进行操作,但不想使用 zip() 函数,也可以使用 itertools.zip_longest() 函数来处理不等长的可迭代对象

  4. map()函数

  • map()函数是一个内置函数,用于对可迭代对象中的每个元素应用指定的函数(对每个元素施加同一种操作),并返回一个包含结果的迭代器(map object),map()函数会将指定的函数应用于iterable中的每个元素,并返回一个包含结果的迭代器,这些结果是将函数应用于每个元素后的返回值。
复制代码
# 方式一:函数+map
def square(x):
    return x ** 2

numbers = [1, 2, 3, 4, 5]
squared_numbers = map(square, numbers)
print(list(squared_numbers))  # 输出:[1, 4, 9, 16, 25]

# 方式二:匿名函数+map
numbers = [1, 2, 3, 4, 5]
squared_numbers = map(lambda x: x ** 2, numbers)
print(list(squared_numbers))  # 输出:[1, 4, 9, 16, 25]
复制代码
  • 需要注意的是,map()函数返回的是一个迭代器,而不是一个列表。如果需要获取结果的列表,可以使用list()函数将迭代器转换为列表。

  5. filter函数

  • filter()函数是一个内置函数,用于从可迭代对象中过滤出满足指定条件的元素,并返回一个包含结果的迭代器。
  • 语法:filter(function, iterable)
    • function是一个函数,可以是内置函数、自定义函数或匿名函数。iterable是一个可迭代对象,例如列表、元组、集合等。
    • filter()函数会将指定的函数应用于iterable中的每个元素,并返回一个只包含满足条件的元素的迭代器
复制代码
# 方式一:函数+filter
def is_even(x):
    return x % 2 == 0

numbers = [1, 2, 3, 4, 5]
even_numbers = filter(is_even, numbers)
print(list(even_numbers))  # 输出:[2, 4]

# 方式二:匿名函数+filter
numbers = [1, 2, 3, 4, 5]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))  # 输出:[2, 4]
复制代码

  6. reduce()函数

  • reduce()函数是functools模块中的一个函数,用于对可迭代对象中的元素进行累积计算,返回一个单个的结果。
  • 语法reduce(function, iterable[, initializer])
    •   function是一个函数,可以是内置函数、自定义函数或匿名函数。iterable是一个可迭代对象,例如列表、元组、集合等。
    •   reduce函数会将指定的函数应用于可迭代对象中的元素,按照从左到右的顺序依次进行计算,并将每次计算的结果作为下一次计算的输入,最终得到一个累积的结果
复制代码
from functools import reduce

# 方式一:函数+reduce
def multiply(x, y):
    return x * y
numbers = [1, 2, 3, 4, 5]
product = reduce(multiply, numbers)
print(product)  # 输出:120

# 方式二:匿名函数+reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # 输出:120
复制代码

 

posted @   little小小  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示