9 Python函数

本篇是 Python 系列教程第 9 篇,更多内容敬请访问我的 Python 合集

1 定义函数

在 Python 中,你可以使用 def 关键字来定义一个函数。函数定义的基本语法如下:

def function_name(parameters):
    # 函数体
    # ...
    return value
  • function_name: 函数的名称。
  • parameters: 函数接受的参数列表。参数是可选的。
  • return: 可选的关键字,用于返回函数的结果。如果没有显式返回值,默认返回 None

1.1 示例:定义一个简单的函数

下面是一个简单的函数示例,该函数接收两个参数并返回它们的和:

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

# 调用函数
sum = add_numbers(5, 3)
print(sum)  # 输出 8

1.2 示例:使用递归函数

递归函数是在函数内部调用自身的函数。下面是一个计算阶乘的递归函数示例:

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

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

2 参数

函数可以接受不同类型的参数,包括位置参数、默认参数、关键字参数和可变参数。

2.1 位置参数

位置参数是根据参数在函数调用中的位置来确定的。

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

greet("Alice")  # 输出 "Hello, Alice"

2.2 默认参数

默认参数允许你在定义函数时为参数设置默认值。

def greet(name, greeting="Hello"):
    print(greeting + ", " + name)

greet("Alice")  # 输出 "Hello, Alice"
greet("Bob", "Hi")  # 输出 "Hi, Bob"

2.3 关键字参数

关键字参数允许你通过参数名称来传递值,这使得函数调用更加清晰。

def describe_person(name, age, occupation):
    print(f"{name} is {age} years old and works as a {occupation}.")

describe_person(name="Alice", age=30, occupation="Engineer")

2.4 可变参数

可变参数允许你在不知道确切参数数量的情况下定义函数。

  • 使用星号 (*args): 接收任意数量的位置参数。
  • 使用双星号 (**kwargs): 接收任意数量的关键字参数。
def concatenate_strings(*args):
    result = ""
    for arg in args:
        result += arg
    return result

concatenated = concatenate_strings("Hello", " ", "world!")
print(concatenated)  # 输出 "Hello world!"

def describe_person(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

describe_person(name="Alice", age=30, occupation="Engineer")

3 作用域

在 Python 中,函数作用域是指在函数内部定义的变量的作用范围。作用域规定了变量的可见性和生命周期。理解作用域对于编写清晰和高效的代码非常重要。下面是一些关于 Python 中作用域的基本概念:

3.1 局部作用域 (Local Scope)

局部作用域指的是在函数内部定义的变量的作用范围。这些变量仅在函数内部可用,并且在函数执行完毕后就会被销毁。

示例:

def my_function():
    x = 10  # x 是局部变量
    print(x)  # 输出 10

my_function()
# print(x)  # 如果在这里尝试访问 x,将会抛出 NameError,因为 x 是局部变量

3.2 全局作用域 (Global Scope)

全局作用域是指在整个程序范围内定义的变量的作用范围。这些变量可以在程序的任何地方访问,除非它们被局部作用域中的同名变量所遮蔽。

示例:

x = 5  # x 是全局变量

def my_function():
    print(x)  # 访问全局变量 x

my_function()
print(x)  # 输出 5

3.3 内嵌作用域 (Enclosing Scope)

当一个函数内部定义了另一个函数时,内部函数可以访问外部函数的局部变量,这种情况称为内嵌作用域。

示例:

def outer_function():
    x = 30  # x 是 outer_function 的局部变量
    
    def inner_function():
        print(x)  # 访问外部函数的局部变量 x
        
    inner_function()

outer_function()

3.4 内建作用域 (Built-in Scope)

Python 自带了一些预定义的全局变量和函数,例如 len()print() 等。这些都位于内建作用域中,可以在程序的任何地方访问。

3.5 LEGB 规则

LEGB 是一个缩写词,代表 Local、Enclosing、Global 和 Built-in,这是 Python 中查找变量的作用域顺序:

  1. Local: 在当前函数的作用域中查找变量。
  2. Enclosing: 如果在当前函数中找不到变量,则向上一级函数的作用域中查找。
  3. Global: 如果在所有内嵌作用域中都找不到变量,则在全局作用域中查找。
  4. Built-in: 最后,在内建作用域中查找。

3.6 nonlocalglobal 关键字

nonlocalglobal 关键字用于声明变量的作用域。

  • nonlocal: 用于声明变量属于最近一个拥有该变量的内嵌作用域。从字面意思“非本地”就能理解并不是本层的。
  • global: 用于声明一个变量属于全局作用域。

示例:

x = 50  # 全局变量
y = 50  # 全局变量


def outer_function():
    x = 100  # outer_function 的局部变量
    y = 100  # outer_function 的局部变量

    def inner_function():
        nonlocal x  # 声明 x 是 outer_function 的局部变量
        x = 200  # 修改 outer_function 的局部变量 x
        print("Inner x:", x) # 输出 200

        global y  # 声明 y 是 全局变量
        print("Inner y:", y)  # 输出 50

    inner_function()

    # 访问 outer_function 的局部变量 x
    print("Outer x:", x)  # 输出 200


outer_function()
print("Global x:", x)  # 输出 50
print("Global y:", y)  # 输出 50

在这个例子中,inner_function 修改了 outer_function 中的 x,而不是创建一个新的局部变量。inner_function修改了全局的y,而不是 outer_function 中的 y

3.7 总结

  • 局部变量只在其定义的函数内部可见。
  • 全局变量在整个程序中可见。
  • 内嵌作用域允许内部函数访问外部函数的局部变量。
  • 内建作用域包含了 Python 的预定义内置函数和变量。
  • 内部函数修改外部函数的变量要先用nonlocal先声明;内部函数修改全局变量要先用global声明。

4 常用内置函数

那可太多了,刚好凑字数(不是)

Python 提供了许多内置函数,这些函数可以帮助你执行各种常见的任务,而无需编写额外的代码。下面是一些常用的内置函数及其说明:

4.1 数据类型转换函数

这些函数用于将一种数据类型转换为另一种数据类型。

  • int(): 将给定的值转换为整数。
int("42")  # 结果是 42
  • float(): 将给定的值转换为浮点数。
float("3.14")  # 结果是 3.14
  • str(): 将给定的值转换为字符串。
str(100)  # 结果是 "100"
  • bool(): 将给定的值转换为布尔值。
bool(1)  # 结果是 True
  • list(): 将给定的值转换为列表。
list("hello")  # 结果是 ['h', 'e', 'l', 'l', 'o']
  • tuple(): 将给定的值转换为元组。
tuple("hello")  # 结果是 ('h', 'e', 'l', 'l', 'o')
  • set(): 将给定的值转换为集合。
set("hello")  # 结果是 {'h', 'e', 'l', 'o'}
  • dict(): 将给定的键值对转换为字典。
dict([(1, "one"), (2, "two")])  # 结果是 {1: "one", 2: "two"}

4.2 控制流相关的函数

这些函数用于控制程序的执行流程。

  • abs(): 返回数值的绝对值。
abs(-5)  # 结果是 5
  • all(): 如果可迭代对象(说白了就是数组)的所有元素都为 True,则返回 True;否则返回 False
all([True, True, True])  # 结果是 True
  • any(): 如果可迭代对象中至少有一个元素为 True,则返回 True;否则返回 False
any([False, True, False])  # 结果是 True
  • enumerate(): 返回一个枚举对象,可以同时获取索引和值。适用场景:处理列表、元组或字符串中的元素时,需要同时访问索引和值。
for index, char in enumerate("hello"):
    print(index, char)
# 输出:
# 0 h
# 1 e
# 2 l
# 3 l
# 4 o

fruits = ["apple", "banana", "cherry", "date"]
for index, fruit in enumerate(fruits):
    print(f"Index: {index}, Fruit: {fruit}")
# 输出
# 0 apple
# 1 banana
# 2 cherry
# 3 date
  • sorted(): 对可迭代对象进行排序。
sorted([3, 1, 2])  # 结果是 [1, 2, 3]
  • reversed(): 返回一个反转的迭代器。注意不能直接打印,需要遍历。
print(reversed([1, 2, 3]))
# 直接打印的花会输出 <list_reverseiterator object at 0x000001526CE4AAA0>

for x in reversed([1, 2, 3]):
    print(x)
# 输出
# 3
# 2
# 1
  • zip(): 将多个可迭代对象打包成一个元组的列表。
for x in zip([1, 2, 3], ['a', 'b', 'c']):
    print(x)
# 输出
# (1, 'a')
# (2, 'b')
# (3, 'c')

4.3 数学相关的函数

这些函数用于执行基本的数学运算。

  • round(): 四舍五入。
round(3.14)  # 结果是 3
  • min(): 返回可迭代对象中的最小值。
min([1, 2, 3])  # 结果是 1
  • max(): 返回可迭代对象中的最大值。
max([1, 2, 3])  # 结果是 3
  • sum(): 返回可迭代对象中的元素之和。
sum([1, 2, 3])  # 结果是 6

4.4 字符串相关的函数

这些函数用于处理字符串。

  • len(): 返回对象的长度。
len("hello")  # 结果是 5
  • str.join(): 使用指定的分隔符连接字符串列表。
"-".join(["a", "b", "c"])  # 结果是 "a-b-c"
  • print(): 打印输出。
print("Hello, world!")  # 输出 "Hello, world!"

4.5 其他常用函数

  • type(): 返回对象的类型。
type(10)  # 结果是 <class 'int'>
  • id(): 返回对象的标识符。
id(10)  # 返回对象的唯一标识符
  • input(): 从标准输入读取一行。
name = input("Enter your name: ")
  • help(): 显示帮助文档。
help(len)  # 显示 len 函数的帮助文档
  • dir(): 列出对象的所有属性和方法。
dir("hello")  # 列出字符串对象的方法和属性
  • eval(): 评估一个字符串,并执行其中的 Python 表达式。
eval("1 + 2")  # 结果是 3
  • exec(): 动态执行 Python 代码。
exec("print('Hello, world!')")  # 输出 "Hello, world!"
  • globals(): 返回一个字典,其中包含了当前模块的全局变量及其值。
# 定义全局变量
x = 10
print(globals())
# 输出,可以在末尾看到变量x
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000017E8933BCB0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\PycharmProjects\\demo1\\Hello.py', '__cached__': None, 'x': 10}

globals() 函数主要用于以下几种情况:

  1. 动态访问全局变量
# 定义全局变量 x = 10 y = 20 # 使用 globals() 访问全局变量 def access_globals():    global_var_x = globals()["x"]    global_var_y = globals()["y"]    print(global_var_x)  # 输出 10    print(global_var_y)  # 输出 20 access_globals()
  1. 检查全局命名空间的内容
# 定义全局变量 x = 10 y = 20 # 检查全局命名空间的内容 def inspect_globals():    global_vars = globals()    for key, value in global_vars.items():        print(key, ":", value) inspect_globals() # 输出 # __name__ : __main__ # __doc__ : None # __package__ : None # __loader__ : <_frozen_importlib_external.SourceFileLoader object at 0x000001EA9BCEBCB0> # __spec__ : None # __annotations__ : {} # __builtins__ : <module 'builtins' (built-in)> # __file__ : D:\PycharmProjects\demo1\Hello.py # __cached__ : None # x : 10 # y : 20 # inspect_globals : <function inspect_globals at 0x000001EA9BE684A0>
  1. 动态创建变量
def create_variable(var_name, var_value):    # 动态创建全局变量    globals()[var_name] = var_value create_variable("z", 30) print(z)  # 输出 30
  1. 调试和开发
  • 在调试或开发过程中,globals() 可以帮助你了解当前模块的状态。

  • locals(): 返回一个字典,其中包含了当前模块的局部变量及其值。作用和上面globals() 函数类似。

locals()  # 返回局部变量的字典
  • callable(): 检查一个对象是否可调用。
callable(print)  # 结果是 True
  • isinstance(): 检查一个对象是否为指定类的实例。
isinstance(10, int)  # 结果是 True
  • getattr(): 获取对象的属性。
getattr("hello", "__len__")()  # 结果是 5,注意后面的()不能省
  • hasattr(): 检查对象是否有指定的属性。
hasattr("hello", "__len__")  # 结果是 True
  • setattr(): 设置对象的属性。
class MyClass:
    pass

obj = MyClass()
setattr(obj, "value", 10)
print(obj.value)  # 输出 10
  • delattr(): 删除对象的属性。
delattr(obj, "value")
  • map(): 允许你对序列中的每个元素应用一个函数,并返回一个新的序列。
map(function, iterable, ...)
# function: 一个函数,将应用于每个元素。
# iterable: 一个或多个可迭代对象(如列表、元组等),其中的每个元素都将被传递给 function。

map() 函数返回一个 map 对象,这个对象是一个迭代器,你可以通过 list()tuple() 或者遍历来获取结果。关于迭代器(iterator)和可迭代对象(iterable)的区别和关系请移步文末。

  • list(): 返回列表,用途包括:

  • 创建空列表。

  • 将迭代器或任何类型可迭代对象转为列表。

  • 复制列表。

函数有太多了,这里就不一一列举了。

5 lambda表达式

在 Python 中,lambda 表达式是一种创建小型匿名函数的方式。它允许你在一行代码内快速定义简单的函数,而无需使用标准的 def 关键字来定义函数。

5.1 语法

lambda arguments: expression
  • lambda 是用来声明表达式的关键词。
  • arguments 一个或多个参数,它们之间用逗号 , 分隔。
  • expression 一个有效的 Python 表达式,该表达式将被计算并作为 lambda 函数的结果返回。

5.2 注意事项

  • lambda 表达式通常用于简单的操作,如果逻辑较为复杂,建议使用传统的 def 关键字定义函数。
  • lambda 函数只能包含一个表达式,不能包含多行代码。

5.3 使用示例

让我们来看几个 lambda 表达式的例子:

5.3.1 简单的 lambda 函数

# 定义一个 lambda 函数,用于计算两个数的和
add = lambda x, y: x + y

# 调用 lambda 函数
result = add(5, 3)
print(result)  # 输出: 8

5.3.2 使用 lambda 函数进行排序

假设我们有一个包含字典的列表,并且我们想按照字典中的某个键来进行排序:

people = [
    {'name': 'Alice', 'age': 25},
    {'name': 'Bob', 'age': 22},
    {'name': 'Charlie', 'age': 30}
]

# 使用 lambda 函数作为 key 参数对列表进行排序
sorted_people = sorted(people, key=lambda person: person['age'])

# 打印排序后的列表
for person in sorted_people:
    print(person)
# 输出结果将根据age进行排序:
# {'name': 'Bob', 'age': 22}
# {'name': 'Alice', 'age': 25}
# {'name': 'Charlie', 'age': 30}

5.3.3 在高阶函数中使用 lambda

Python 中的 map(), filter(), reduce() 等函数都可以接受 lambda 函数作为参数。

  • 使用 map() 函数(上面已经介绍map()函数的功能):
numbers = [1, 2, 3, 4, 5]
squares = map(lambda x: x**2, numbers)
print(list(squares))  # 输出: [1, 4, 9, 16, 25]
  • 使用 filter() 函数(功能是过滤值):
numbers = [1, 2, 3, 4, 5]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))  # 输出: [2, 4]
  • 使用 reduce() 函数(功能是做累积)需要导入 functools 模块:
from functools import reduce

numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # 输出: 120

拓展:

迭代器(iterator)和可迭代对象(iterable) 是两个紧密相关的概念,它们都能实现循环遍历。通常通过调用可迭代对象的 __iter__ 方法来创建迭代器。

下面是一个简单的例子,演示如何使用可迭代对象和迭代器:

# 定义一个可迭代对象(列表)
my_list = [1, 2, 3, 4, 5]

# 获取该可迭代对象的迭代器,两种方式均可
# iterator = iter(my_list)
iterator = my_list.__iter__()

# 使用迭代器遍历列表
while True:
    try:
        item = next(iterator)
        print(item)
    except StopIteration:
        break

Q: 可迭代对象有哪些?

A: 很多,列表(List)、元组(Tuple)、字典(Dictionary)、集合(Set)、甚至字符串(String)、范围(Range)都是。

Q: 如何创建迭代器?

A: 使用 iter() 和 next() 方法。

posted @ 2024-08-28 16:44  凡人编程传(Java)  阅读(186)  评论(0编辑  收藏  举报