【深度学习】 Python 和 NumPy 系列教程(七):Python函数

目录

一、前言

二、实验环境

三、Python函数基础

1. 定义函数

2. 参数传递

3. 函数调用

4. 返回值

5. 函数文档字符串

四、将函数存储在模块中

1. 创建模块

2. 导入模块

a. import 模块名

b. from 模块名 import 函数名

c. from 模块名 import *

五、多种形式的函数

1. 普通函数

2. 匿名函数(Lambda函数)

3. 内置函数

4. 递归函数

a. 递归概念

b. 递归条件

5. 高阶函数

6. 装饰器函数

7. 生成器函数

8. 异步函数

9. 偏函数


一、前言

        Python是一种高级编程语言,由Guido van Rossum于1991年创建。它以简洁、易读的语法而闻名,并且具有强大的功能和广泛的应用领域。Python具有丰富的标准库和第三方库,可以用于开发各种类型的应用程序,包括Web开发、数据分析、人工智能、科学计算、自动化脚本等。

        Python本身是一种伟大的通用编程语言,在一些流行的库(numpy,scipy,matplotlib)的帮助下,成为了科学计算的强大环境。本系列将介绍Python编程语言和使用Python进行科学计算的方法,主要包含以下内容:

  • Python:基本数据类型、容器(列表、元组、集合、字典)、函数、类
  • Numpy:数组、数组索引、数据类型、数组数学、广播
  • Matplotlib:绘图,子图,图像
  • IPython:创建笔记本,典型工作流程

二、实验环境

numpy 1.21.6
python 3.7.16
  • 运行下述命令检查Python版本
 python --version 
  • 运行下述代码检查Python、NumPy版本
import sys
import numpy as np

print("Python 版本:", sys.version)
print("NumPy 版本:", np.__version__)

三、Python函数基础

        Python函数指的是一段可重复使用的代码块,用于执行特定的任务。函数接受输入参数(可选)并返回一个输出结果(也可选)。Python函数有以下几个关键特点:

1. 定义函数

        使用关键字def来定义函数。函数定义包括函数名、参数列表和函数体。

def add_numbers(a, b):
    sum = a + b
    return sum

        上述代码定义了一个名为add_numbers的函数,它接受两个参数ab,并返回它们的和。

2. 参数传递

        函数可以接受零个或多个参数。参数可以是必需的(必须提供)或可选的(可以省略)。函数在调用时通过参数来接收输入值。

def greet(name):
    print("Hello, " + name + "!")

        上述代码定义了一个名为greet的函数,它接受一个名为name的参数,并打印出问候语。

3. 函数调用

        要调用函数,可以使用函数名和相应的参数列表。

result = add_numbers(3, 4)
print(result)

        上述代码调用了add_numbers函数,并将返回的结果赋值给result变量,然后打印出结果。

4. 返回值

        函数可以使用return语句返回一个值。返回值可以是任意类型的对象,如数字、字符串、列表等。

def multiply_numbers(a, b):
    product = a * b
    return product

        上述代码定义了一个名为multiply_numbers的函数,它接受两个参数ab,并返回它们的乘积。

5. 函数文档字符串

        为了方便其他开发人员理解函数的用途和使用方法,可以在函数内部使用文档字符串(docstring)进行注释。文档字符串是位于函数定义之后的字符串,可以通过help()函数或.__doc__属性来查看。

def add_numbers(a, b):
    """
    This function adds two numbers and returns the result.
    """
    sum = a + b
    return sum


help(add_numbers)

print(add_numbers.__doc__)

        

四、将函数存储在模块中

1. 创建模块

        创建一个新的Python文件,并命名为希望的模块名(例如my_module.py)。在该文件中,定义函数和其他相关代码。

def add_numbers(a, b):
    return a + b

def multiply_numbers(a, b):
    return a * b

# 其他函数和代码...

        保存文件并将其放在Python解释器可以访问的位置。通常,可以将模块文件与调用它的代码文件放在同一个目录中。

2. 导入模块

        将函数存储在模块中可以提高代码的组织性和可重用性。模块是一种将相关功能封装在一起的方式,可以在项目中的多个文件中使用它们,并且可以与其他开发人员共享和重用。

a. import 模块名

        在另一个Python脚本中,通过使用import语句导入创建的模块。

import my_module

result = my_module.add_numbers(3, 5)
print(result)  # 输出:8

result = my_module.multiply_numbers(2, 4)
print(result)  # 输出:8

        通过import语句导入模块后,就可以使用模块中定义的函数和其他代码。可以通过模块名.函数名的方式来调用模块中的函数。

b. from 模块名 import 函数名

        使用from 模块名 import 函数名的形式,可以直接使用函数名调用,而无需使用模块名作为前缀。    

from my_module import add_numbers

result = add_numbers(3, 5)
print(result)  # 输出:8

        这种方式可以选择性地导入模块中的特定函数或变量,以便更方便地使用它们。

c. from 模块名 import *

        使用from 模块名 import *的方式可以导入模块中的所有函数和变量。这种导入方式将模块中所有的公开(没有以下划线开头的)函数和变量都导入到当前命名空间中。

        然而,建议尽量避免使用from 模块名 import *的方式导入模块,特别是在大型项目中。这是因为这种方式可能导致命名空间污染和命名冲突的问题。当导入的模块中有多个函数或变量与当前命名空间中的名称相同时,会发生命名冲突,导致不可预料的行为。

        相反,推荐使用显式导入的方式,即使用from 模块名 import 函数名import 模块名的形式。这样可以明确指定要导入的函数或模块,并且在使用时可以清楚地知道其来源。

        如果确实需要导入模块中的所有函数和变量,可以使用import 模块名的方式导入整个模块,并在使用时通过模块名.函数名的方式来调用它们。这样可以避免命名冲突,并且更清晰地表达代码的意图。

五、多种形式的函数

1. 普通函数

        普通函数是最常见的函数形式,由def关键字定义,可以接受参数并返回值。

def add_numbers(a, b):
    return a + b

result = add_numbers(3, 5)
print(result)  # 输出:8

2. 匿名函数(Lambda函数)

        匿名函数(lambda函数)是一种没有函数名的简单函数形式。它通常用于需要一次性定义并使用的简单函数。匿名函数使用lambda关键字定义,并可以包含一个或多个参数和一个表达式作为函数体。以下是一个使用匿名函数计算两个数的和的示例:

add_numbers = lambda a, b: a + b
result = add_numbers(3, 5)
print(result)  # 输出:8

3. 内置函数

        Python提供了许多内置函数,这些函数是Python解释器提供的预定义函数,可以直接使用。这些内置函数包括len()print()range()type()等等,用于执行各种常见的操作。以下是一些常用的内置函数的示例:

# 获取字符串长度
length = len("Hello, world!")
print(length)  # 输出:13

# 打印文本
print("Hello, world!")

# 生成整数序列
numbers = list(range(1, 6))
print(numbers)  # 输出:[1, 2, 3, 4, 5]

# 获取对象类型
print(type(numbers))  # 输出:<class 'list'>

4. 递归函数

a. 递归概念

        函数递归是指函数在其函数体内调用自身的过程。递归函数通常包含两个部分:基本情况和递归情况。

  • 基本情况是指函数停止递归的条件。当满足基本情况时,递归函数不再调用自身,而是返回一个特定的值或执行其他操作。
  • 递归情况是指函数继续递归调用自身的条件。在递归情况下,函数会通过传递不同的参数值来解决更小规模的问题。通过不断缩小问题的规模,最终达到基本情况,从而结束递归。

b. 递归条件

递归函数需要满足以下两个重要条件:

  • 基本情况:必须存在一个或多个基本情况,用于终止递归并返回特定的值或执行特定的操作。

  • 收敛性:递归调用必须朝着基本情况逼近。也就是说,在每次递归调用中,问题的规模都应该比上一次递归调用要小,最终达到基本情况。

        如果递归函数没有正确定义基本情况或无法收敛,就会导致无限递归,最终导致栈溢出或程序崩溃。递归函数在某些情况下可以提供一种简洁、优雅的解决方案。然而,递归的执行过程相对于迭代(循环)来说更消耗内存和时间,因此在使用递归时需要注意问题规模和性能。

        下面是一个经典的递归函数示例,计算一个正整数的阶乘:

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

result = factorial(5)
print(result)  # 输出:120

        在上述代码中,当n等于0时,递归函数返回1作为基本情况。否则,递归函数计算nfactorial(n - 1)的乘积作为递归情况。

5. 高阶函数

        高阶函数是一种可以接受函数作为参数或返回函数的函数形式。在Python中,函数是一等公民,因此可以像任何其他对象一样进行传递和操作。高阶函数可以用于实现函数的组合、过滤、映射等操作。例如,map()filter()是常见的高阶函数,用于对可迭代对象进行映射和过滤操作。以下是一个使用map()filter()的示例:

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

# 使用map()函数将每个数平方
squared_numbers = list(map(lambda x: x**2, numbers))
print(squared_numbers)  # 输出:[1, 4, 9, 16, 25]

# 使用filter()函数过滤出偶数
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出:[2, 4]

        在上面的例子中,map()函数将每个数平方,并使用lambda x: x**2作为映射函数。filter()函数过滤出偶数,并使用lambda x: x % 2 == 0作为过滤函数。

6. 装饰器函数

  • 装饰器函数是一种特殊的函数,用于修改其他函数的行为或功能。
    • 装饰器函数通常接受一个函数作为输入,并返回一个新的函数作为输出。
    • 装饰器函数可以在不修改原始函数代码的情况下,通过添加额外的功能来扩展函数的行为。
  • 下面是一个简单的装饰器函数,用于在函数调用前后打印日志:
def logger(func):
    def wrapper(*args, **kwargs):
        print("Calling function:", func.__name__)
        result = func(*args, **kwargs)
        print("Function", func.__name__, "finished execution")
        return result
    return wrapper

@logger
def add_numbers(a, b):
    return a + b

result = add_numbers(3, 5)
print(result)  # 输出:8

        在上面的例子中,logger装饰器函数接受一个函数作为输入,并返回一个新的函数wrapperwrapper函数在调用被装饰的函数之前和之后打印日志信息。

7. 生成器函数

  • 生成器函数是一种特殊的函数,可以用于定义生成器。
    • 生成器是一种特殊的迭代器,可以按需生成值,而不是一次性生成所有值。
    •  生成器函数使用yield关键字来定义生成器的每个元素。
    • 每次调用生成器的next()函数或使用for循环迭代时,生成器函数会从上次暂停的位置继续执行,并生成下一个值。
    • 这种按需生成值的方式可以提高性能和节省内存。
  • 下面是一个生成斐波那契数列的生成器函数:
def fibonacci_generator():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci_generator()
print(next(fib))  # 输出:0
print(next(fib))  # 输出:1
print(next(fib))  # 输出:1
print(next(fib))  # 输出:2
# ...

# 使用for循环打印斐波那契数列的前十个数
fib = fibonacci_generator()
for _ in range(10):
    print(next(fib))

        在上面的例子中,fibonacci_generator生成器函数使用yield关键字定义了一个生成斐波那契数列的生成器。每次调用next(fib)时,生成器会生成下一个斐波那契数列的值。

8. 异步函数

        异步函数是一种用于异步编程的函数形式,可以使用async关键字定义。异步函数通常与await关键字一起使用,用于处理异步操作,例如网络请求、文件读写等。异步函数能够提高程序的并发性能和响应性,允许在等待某些操作完成时执行其他任务。以下是一个简单的异步函数的示例:

import asyncio

async def greet(name):
    print("Hello, " + name)
    await asyncio.sleep(1)
    print("Goodbye, " + name)

asyncio.run(greet("Alice"))

        在上面的例子中,greet异步函数使用await关键字等待异步操作asyncio.sleep(1)完成。在等待期间,可以执行其他任务。这样的异步函数可以在需要等待I/O操作的情况下提高程序的性能。

9. 偏函数

        偏函数是一种固定函数部分参数的函数形式。它通过使用functools.partial()函数来创建一个新的函数,该函数固定了原始函数的部分参数。偏函数可以用于简化函数调用,减少重复代码。以下是一个使用偏函数的示例:

import functools

def power(base, exponent):
    return base ** exponent

square = functools.partial(power, exponent=2)
cube = functools.partial(power, exponent=3)

print(square(4))  # 输出:16,等同于 power(4, 2)
print(cube(4))  # 输出:64,等同于 power(4, 3)

        在上面的例子中,functools.partial()函数创建了两个新的偏函数squarecube,它们是power函数的特定版本,其中exponent参数被固定为2和3。

猜你喜欢

转载自blog.csdn.net/m0_63834988/article/details/132790623