【 Python 全栈开发 ⑮ 】函数、递归(推)函数、匿名函数与内置函数

文章目录

  • 一、函数
    • (1)函数的构成
      • 函数名
      • 参数
      • 返回值
    • (2)局部变量与全局变量
  • 二、递归函数与递推函数
    • (1)递归函数
    • (2)递推函数
  • 三、匿名函数
  • 四、内置函数


一、函数

Python 函数是一段封装了特定功能的可重复使用的代码块,它们接受任意数量的输入参数并返回结果。

函数可以 节省重复代码 并增加代码的 可读性可维护性。在 Python 中可以使用 def 关键字定义函数,它的语法如下:

def function_name(parameters):
    function_body
    return [expression]

其中,function_name 是函数的名称,parameters 是函数的参数列表,function_body 是函数体,可以包含语句、表达式和控制结构,return 语句可选,用于返回函数的结果。

函数的调用需要使用函数名和参数列表,可以作为表达式的一部分或者作为语句来调用。


(1)函数的构成

函数名

在 Python 中,函数名的命名要求与其他变量的命名方式相同。具体来说,函数名必须符合以下规则:

  1. 函数名必须以字母或下划线开头,不能以数字开头。
  2. 函数名只能包含字母、数字和下划线。
  3. 函数名不能包含空格或其他特殊字符。
  4. 函数名应该简短、明确、易于理解,建议使用小写字母和下划线来表示单词之间的分隔。

另外,Python 还有一些命名规范,可以参考 PEP 8。其中,函数名的命名规范建议使用小写字母和下划线来表示单词之间的分隔,如下所示:

def function_name():
    pass

这种命名风格可以提高代码的可读性和可维护性,同时也符合 Python 社区的通用惯例。


参数

参数的概念分为 形参(formal parameter实参(actual parameter 两种。

形参是在定义函数时指定的参数,它们只存在于函数的定义中,作为函数的一部分实现。实参是在调用函数时传递给函数的值,它们存在于函数调用的上下文中。

简单来说,形参就是函数定义时的参数,实参就是函数调用时传入的参数值。


函数参数有四种类型:

  1. 位置参数:位置参数是函数定义中的参数,按照位置从左到右传递的参数。调用函数时,必须以相同的顺序传递参数。

    例如:

    def greet(name, message):
        print(f"{name}, {message}")
    
    greet("Sam", "Hello!")  # 输出:Sam, Hello!
    
  2. 关键字参数:在调用函数时,使用参数名和值的形式传递参数。使用关键字参数可以不按照顺序传递参数。

    例如:

    def greet(name, message):
        print(f"{name}, {message}")
    
    greet(message="Hello!", name="Sam")  # 输出:Sam, Hello!
    
  3. 默认参数:默认参数是指在函数定义时,给参数指定一个默认值。如果在调用函数时没有传递这个参数,函数就会使用默认值。如果传递了这个参数,则使用传递的值。

    例如:

    def greet(name, message="Hello!"):
        print(f"{name}, {message}")
    
    greet("Sam")  # 输出:Sam, Hello!
    greet("Sam", "Hi!")  # 输出:Sam, Hi!
    
  4. 不定长参数:不定长参数是指函数定义中没有指定参数个数的参数。不定长参数分为两种类型:

    • *args:允许函数接收任意数量的位置参数,并将这些参数作为一个元组传递给函数。

      例如:

      def add(*args):
          total = 0
          for num in args:
              total += num
          return total
      
      print(add(1, 2, 3, 4))  # 输出:10
      
    • **kwargs:允许函数接收任意数量的关键字参数,并将这些参数作为一个字典传递给函数。

      例如:

      def display_info(**kwargs):
          for key, value in kwargs.items():
              print(f"{key}: {value}")
      
      display_info(name="Sam", age=30, city="New York")  # 输出:name: Sam, age: 30, city: New York
      

以上四种参数类型可以组合使用。例如:

def greet(name, message="Hello!", *args, **kwargs):
    print(f"{name}, {message}")
    for arg in args:
        print(arg)
    for key, value in kwargs.items():
        print(f"{key}: {value}")

greet("Sam", "Hi!", "Nice to meet you.", "How are you?", age=30, city="New York")
# 输出:
# Sam, Hi!
# Nice to meet you.
# How are you?
# age: 30
# city: New York

在这个例子中,位置参数 name 和默认参数 message 指定了函数的必需参数,在其后使用了 *args 和 **kwargs 来接收不定长参数。

在 Python 中,可以使用类型注释来为函数的参数指定类型,类型注释是在参数名和冒号之间使用 “: 类型” 来表示。例如,如果您要为一个接收两个浮点数参数的函数指定参数类型,则可以这样写:

def add_numbers(x: float, y: float) -> float:
    return x + y

在这个例子中,类型注释 x: floaty: float 指定了参数的类型为浮点数。这种注释方式是可选的,但是它可以提供更好的可读性和类型检查。

需要注意的是,类型注释只是一种提示,它不会强制执行参数的类型。使用类型注释有利于代码的可读性和可维护性,但并不会改变 Python 解释器的行为。


返回值

函数的返回值可以用于各种方式,以下是几个常见的用法:

  1. 赋值给一个变量:
def add(a, b):
    return a + b

result = add(2, 3)
print(result) # 输出 5
  1. 作为另一个函数的参数:
def subtract(a, b):
    return a - b

result = subtract(add(2, 3), 1)
print(result) # 输出 4
  1. 直接打印:
print(add(2, 3)) # 输出 5
  1. 作为一个条件语句的判断条件:
def is_positive(number):
    return number > 0

if is_positive(add(2, 3)):
    print("The result is positive.")
else:
    print("The result is negative or zero.")

总之,函数的返回值可以用于各种方式,开发者需要根据具体的需求选择合适的方式。


(2)局部变量与全局变量

在 Python 中,全局变量和局部变量是两种不同的变量作用域。全局变量在整个程序中都可以访问,而局部变量只能在定义它的函数内部使用。

全局变量是在程序的顶层定义的变量,可以在程序的任何地方访问。如果在函数内部使用了全局变量,需要在函数中使用 global 关键字来声明这个变量。

局部变量是在函数内部定义的变量,只能在函数内部使用。在函数结束时,局部变量将被销毁。如果在函数内部有和全局变量同名的变量,Python 将优先使用局部变量,而不是全局变量。

以下示例程序演示了全局变量和局部变量的使用:

# 定义一个全局变量
global_var = 10

# 定义一个函数,使用局部变量
def my_func():
    local_var = 20
    print("局部变量 local_var = ", local_var)

# 调用函数
my_func()

# 在函数外访问全局变量
print("全局变量 global_var = ", global_var)

输出结果为:

局部变量 local_var =  20
全局变量 global_var =  10

在上面的程序中,global_var 是一个全局变量,可以在程序的任何地方访问。my_func() 函数中定义了一个局部变量 local_var,只在函数内部可用。函数调用结束后,local_var 变量将被销毁。调用 my_func() 函数和打印 global_var 变量都可以正常运行,说明全局变量和局部变量的使用没有冲突。

二、递归函数与递推函数

递归函数和递推函数都是函数的一种,但它们的计算方式不同。


(1)递归函数

递归函数是指在函数内部调用自身的函数。递归函数一般包括两个部分,一个是递归终止条件,另一个是递归操作。递归函数的特点是代码简单易懂,但在计算效率方面可能不如递推函数。

例如,以下是一个计算阶乘的递归函数:

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

在这个函数里,当n等于0时,递归终止,返回1;否则,函数调用自身,传入n-1作为参数,并将其结果乘以n。

在编写递归算法时,需要考虑以下要点:

  1. 设计 递归结束条件:我们需要定义一个递归结束的条件,否则递归函数会无限调用下去,直到栈溢出。

  2. 设计 递推公式:我们需要设计递归公式,即如何将原问题转化为子问题。

  3. 控制 递归深度:递归算法的深度不宜过深,否则会极大地增加时间和空间复杂度。

  4. 优化 递归算法:递归算法要尽量避免重复计算,可以通过记忆化搜索等方式来优化。

  5. 理解 递归堆栈:由于递归算法是通过堆栈来实现的,因此需要理解堆栈的工作原理。

  6. 注意 边界情况:递归算法在处理边界情况时需要特别注意,防止出现数组越界等错误。

以上是编写递归算法时需要注意的要点,只有掌握了这些要点才能编写出高效、稳定的递归算法。


(2)递推函数

递推函数是指通过已知的初始值,按照一定的规律不断推导出后续的值。递推函数的特点是计算效率高,但代码可读性可能稍差。

例如,以下是一个计算斐波那契数列的递推函数:

def fibonacci(n):
    if n < 2:
        return n
    else:
        a, b = 0, 1
        for i in range(2, n + 1):
            a, b = b, a + b
        return b

在这个函数里,当n小于2时,返回n;否则,通过循环计算出斐波那契数列的第n项。

在编写递推算法时,需要考虑以下要点:

  1. 定义 递推公式:我们需要设计递推公式,即如何将原问题转化为子问题。

  2. 确定 初始值:我们需要确定递推的初始值,以便于递推的进行。

  3. 理清 递推顺序:递推算法的顺序非常重要,需要确保子问题先于父问题计算,否则会导致计算结果错误。

  4. 控制 递推次数:递推算法需要控制递推次数,否则会增加时间和空间复杂度。

  5. 避免 重复计算:递推算法需要避免重复计算,可以通过记忆化搜索等方式来优化。

  6. 注意 边界情况:递推算法在处理边界情况时需要特别注意,防止出现数组越界等错误。

以上是编写递推算法时需要注意的要点,只有掌握了这些要点才能编写出高效、稳定的递推算法。


递归算法和递推算法都是解决问题的有效手段,但它们适用于不同的问题情况。

递归算法适用于以下情况:

  1. 问题能够被拆分成多个相似的子问题,这些子问题与原问题具有相同的性质。

  2. 问题的解决过程可以通过不断地将问题转化为更小的子问题来实现。

  3. 问题的解可以通过将子问题的解组合而成。

递归算法通常使用递归函数的调用栈来存储子问题的状态,因此在递归深度较大的情况下会消耗大量的内存,容易导致栈溢出等问题。

递推算法适用于以下情况:

  1. 问题能够被拆分成多个相似的子问题,这些子问题与原问题具有相同的性质。

  2. 问题的解决过程可以通过依次求解子问题来实现。

  3. 问题的解可以通过将子问题的解组合而成。

递推算法通常不需要使用递归函数的调用栈,因此可以避免栈溢出等问题,但是也需要考虑控制递推次数和避免重复计算等问题。递推算法通常效率较高,可以处理大规模的问题。

综上所述,递归算法和递推算法各有优缺点,应根据问题的特点选择合适的算法来解决问题。


三、匿名函数

匿名函数是一种没有被命名的函数。它通常在需要函数作为参数或者需要一个临时函数的情况下使用。匿名函数可以直接传递给其它函数,或者保存在变量中进行后续的使用。

在一些编程语言中,匿名函数也被称作 Lambda 函数或者闭包函数。

匿名函数的主要用法是作为另一个函数的参数或者返回值。在这种情况下,匿名函数提供了一种快速、简便的方式来定义函数而不必使用传统的函数定义方式。

在Python中,可以通过 lambda 关键字来定义一个匿名函数。匿名函数的语法如下:

lambda arguments: expression

其中 arguments 是函数的参数,可以有多个参数,用逗号分隔。expression 是函数体,可以是任何表达式。匿名函数的返回值是函数体的值。

下面是一个例子,使用匿名函数对列表中的元素进行平方运算:

# 使用匿名函数对列表中的元素进行平方运算

my_list = [1, 2, 3, 4, 5]

squared_list = list(map(lambda x: x**2, my_list))

print(squared_list)  # [1, 4, 9, 16, 25]

在这个例子中,使用了 Python 内置的 map 函数,将列表 my_list 中的每个元素传递给匿名函数,进行平方运算,并返回一个新的列表。

匿名函数的主要用法是作为另一个函数的参数或者返回值。在这种情况下,匿名函数提供了一种快速、简便的方式来定义函数而不必使用传统的函数定义方式。


匿名函数与普通函数相比,具有以下优势和劣势:

优势:

  1. 简洁:匿名函数通常只有一行代码,定义简单,不需要像普通函数那样定义函数名、参数等信息。
  2. 灵活:匿名函数可以作为参数传递给其他函数,非常灵活,能够不依赖于函数名的方式被调用。
  3. 一次性使用:匿名函数通常用于一次性用途,可以避免定义冗余的函数。

劣势:

  1. 只能包含 单个表达式:匿名函数一般只能包含单个表达式,而普通函数可以包含多个语句。
  2. 可读性差:由于没有函数名和参数名的标示,匿名函数可读性较差,不容易理解。
  3. 调试困难:由于匿名函数没有名称,调试困难,不能直接查看函数栈。

四、内置函数

内置函数是 Python 解释器中默认存在的一些函数。这些函数不需要导入任何模块,可以在任何地方直接使用。

Python 的内置函数非常多,包括了各种基本的操作和功能,比如数学运算、类型转换、字符串处理、文件操作等,以及常用的数据结构和算法函数,如列表操作、字典操作、排序、过滤等。

除了内置函数,Python 还有许多常用的标准库函数和第三方库函数,可以通过导入相应的模块来使用。

以下是Python 3.9.0版本的所有内置函数,按字母顺序排列:

函数名 描述
abs() 返回一个数的绝对值
all() 接受一个可迭代对象,返回True如果所有元素都为True或为空
any() 接受一个可迭代对象,返回True如果至少一个元素为True
ascii() 返回一个字符串的ASCII编码版本
bin() 将整数转换为二进制字符串
bool() 用来将一个值转换为布尔类型
breakpoint() 在调试模式下使用,将程序暂停并进入调试模式
bytearray() 返回一个字节数组
bytes() 返回一个不可变的字节数组
callable() 检查一个对象是否可以调用
chr() 将一个Unicode编码转换为字符
classmethod() 将一个方法转换为类方法
compile() 将源代码编译成代码或AST对象
complex() 返回一个复数
delattr() 删除一个对象的属性
dict() 创建一个字典
dir() 返回一个对象的所有属性和方法的列表
divmod() 返回两个数的商和余数的元组
enumerate() 返回一个可迭代序列的枚举对象,包含元素的索引和值
eval() 将表达式作为Python代码执行
exec() 在当前作用域中执行一段Python代码
filter() 过滤可迭代对象中的元素,返回一个由满足条件的元素所组成的迭代器
float() 返回一个浮点数
format() 将一个值格式化为字符串
frozenset() 返回一个不可变的集合
getattr() 返回一个对象的属性的值
globals() 返回全局变量的字典
hasattr() 判断一个对象是否有某个属性
hash() 返回一个对象的哈希值
help() 返回函数或模块的帮助信息
hex() 将整数转换为十六进制字符串
id() 返回一个对象的唯一标识符
input() 从标准输入获取一个值
int() 返回一个整数
isinstance() 判断一个对象是否是某个类的实例
issubclass() 判断一个类是否是另一个类的子类
iter() 返回一个可迭代对象的迭代器
len() 返回一个对象的长度或元素个数
list() 创建一个列表
locals() 返回当前作用域中的变量字典
map() 将函数应用于可迭代对象中的每个元素,返回一个由结果组成的列表
max() 返回可迭代对象中的最大值或多个参数中的最大值
memoryview() 返回一个对象的memory view
min() 返回可迭代对象中的最小值或多个参数中的最小值
next() 返回迭代器的下一个元素
object() 创建一个基本对象
oct() 将整数转换为八进制字符串
open() 打开文件并返回文件对象
ord() 返回一个字符的Unicode编码
pow() 返回一个数的幂
print() 输出一个或多个值到标准输出
property() 用于创建属性
range() 创建数字序列
repr() 返回一个对象的字符串表示形式
reversed() 反转可迭代对象中的元素并返回迭代器
round() 返回一个数的四舍五入值
set() 创建一个集合
setattr() 设置一个对象的属性的值
slice() 返回一个切片对象
sorted() 排序可迭代对象中的元素,返回一个列表或迭代器
staticmethod() 将一个方法转换为静态方法
str() 返回一个字符串
sum() 返回可迭代对象中的所有元素的总和
super() 返回一个父类的代理对象
tuple() 创建一个元组
type() 返回一个对象的类型
vars() 返回一个对象的__dict__属性
zip() 将多个可迭代对象的元素压缩成一个元组,并返回一个迭代器

这些内置函数的使用方法可以根据具体的函数调用方式和参数要求进行学习,参考 Python 官方文档或其他相关教程。

你可能感兴趣的:(Python,全栈开发,#,【第一章】语法基础,python,开发语言)