本篇是 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

1.3 函数的使用是否需要“()”

在Python中,是否需要在方法调用时带上括号取决于你是想要调用该方法还是仅仅引用该方法。下面是一些基本规则:

1.3.1 方法调用需要括号

当你想要执行一个方法并可能传递参数时,需要加上括号。这是最常见的用法。

示例:

def say_hello(name):
        print(f"Hello, {name}!")

say_hello("Alice")  # 调用方法,需要括号
1.3.2 引用方法不需要括号

当你只是想获取对方法的引用而不是立即执行它时,不需要括号。这通常发生在需要传递方法作为参数或者将其赋值给变量时。

示例:

def say_hello(name):
    print(f"Hello, {name}!")

# 将方法引用赋值给变量
hello_method = say_hello # 引用方法,不需要括号

# 后续可以调用这个方法引用
hello_method("Bob")  # 调用方法,需要括号

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

2.5 指定参数类型或返回值类型

Python 3.5版本后可以通过“:”指定参数类型,通过“->”指定返回值类型。

def greet(name: str) -> str:
    return 'Hello, ' + name

# 使用
greet("Alice")  # 正确
greet(123)      # 运行报TypeError错,但Python运行时不会阻止你这样做

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() 方法。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部