1.变量的作用域(global与nonlocal)
Python中的变量作用域可以通过global
和nonlocal
关键字来管理。
-
全局变量:在Python中,使用
global
关键字可以在函数内部访问和修改全局变量。当需要在函数内部对全局变量进行操作时,应使用global
关键字声明该变量,这样函数内部的操作就会影响到全局变量。例如,如果希望在函数内部修改一个全局变量的值,可以在函数开始处使用global 变量名
的语句来声明该变量为全局变量。
# 全局变量在哪里都可以使用
a = 10
print(a)
def one_fun():
a = 10
print(a)
print(a)
'''
输出结果为:
10
10
10
'''
# 但是函数结构内的只是调用,可以更改可变类型数据,不可以更改不可变类型数据
a = 10
print(a)
def one_fun():
a = 20
print(a)
print(a)
'''
输出结果为:
10
20
10
'''
data = [
{
"name": "xcy"
}
]
def one_fun():
global data
data = [
{
"name": "xixi"
}
]
print(data)
one_fun()
print(data)
'''
输出结果为:
[{'name': 'xixi'}]
[{'name': 'xixi'}]
'''
# 如果是想要在函数体中更改全局变量的值需要引入global
a = 10
print(a)
def one_fun():
global a
a = 20
print(a)
print(a)
'''
输出结果为:
10
20
20
'''
-
嵌套作用域变量:对于嵌套作用域中的变量,Python提供了
nonlocal
关键字。当需要在嵌套函数中修改外部函数的变量时,应使用nonlocal
关键字声明该变量。nonlocal
关键字允许内部函数修改外部函数的局部变量,而不会创建新的局部变量。它只向上查找一层作用域来寻找变量,如果上一层没有找到,则会继续向上查找,直到找到或者到达全局作用域。如果上一层也没有找到该变量,使用nonlocal
会报错,因为它无法向上追溯到全局作用域。
a = 10
print(a)
def one_fun():
a = 20
def two_fun():
a = 20
print(a)
print(a)
'''
输出结果为:
10
20
10
'''
# 想要改变外部函数的值则需要引入nonlocal
a = 10
print(a)
def one_fun():
a = 20
def two_fun():
nonlocal a
a = 30
print(a)
print(a)
'''
输出结果为:
10
30
10
'''
# 需要注意的是,nonlocal只能改变外部函数中的变量值,不影响全局变量
-
作用域规则:在Python中,变量的作用域遵循LEGB规则,即Local(局部作用域)、Enclosing(嵌套作用域)、Global(全局作用域)和Built-in(内建作用域)。变量的查找顺序是从当前作用域开始,然后到嵌套作用域,再到全局作用域,最后到内建作用域。如果在一个作用域内找不到变量,Python会在父级作用域中继续查找,直到找到该变量或到达全局作用域。
global
和nonlocal
关键字在Python中用于管理变量的作用域,使得函数内部可以访问和修改全局变量或嵌套作用域中的变量。正确使用这些关键字有助于更好地控制变量的可见性和生命周期,从而编写更清晰、更可维护的代码。
2.递归函数
递归函数在编程中是一种重要的概念,特别是在解决涉及自相似问题的时候非常有用。在 Python 中,递归函数是指在函数定义中调用函数本身的函数。
递归函数调用自身,问题被分解为一个或多个更小的子问题,然后再次调用相同的函数来解决这些子问题,最后,递归函数一定有一个递归出口,递归函数不再调用自身,从而避免无限循环。
# 递归求和
def get_num(v):
if v == 1:
return 1
else:
return v + get_num(v - 1)
# 递归求阶乘
def get_multi(v):
if v == 1:
return 1
else:
return v * get_multi(v - 1)
# 递归求阶乘和
def get_multi_sum(v):
if v == 1:
return 1
else:
return get_multi(v) + get_multi_sum(v - 1)
print(get_multi_sum(5))
'''
递归求阶乘和结合了递归求和、递归求阶乘两个,执行结果为153
'''
需要注意的是,递归函数是有递归深度的,在Python中,递归函数默认递归深度为1000,如果我们想要改变递归函数深度的值,我们可以调用 sys。
sys
import sys
a = 10
b = 20
if a > b:
sys.exit()
print(a)
print(sys.argv)
print(sys.argv[1:])
# print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
def get_num(v):
if v == 1:
return 1
else:
return v + get_num(v - 1)
print(get_num(1999))
'''
此时,递归深度就达到了2000
'''
3.匿名函数
Python 使用 lambda 来创建匿名函数。
lambda 函数是一种小型、匿名的、内联函数,它可以具有任意数量的参数,但只能有一个表达式。
匿名函数不需要使用 def 关键字定义完整函数。
lambda 函数通常用于编写简单的、单行的函数,通常在需要函数作为参数传递的情况下使用,例如在 map()、filter()、reduce() 等函数中。
lambda 函数特点:
- lambda 函数是匿名的,它们没有函数名称,只能通过赋值给变量或作为参数传递给其他函数来使用。
- lambda 函数通常只包含一行代码,这使得它们适用于编写简单的函数。
lambda 语法格式:
lambda arguments: expression
lambda
是 Python 的关键字,用于定义 lambda 函数。
arguments
是参数列表,可以包含零个或多个参数,但必须在冒号(:
)前指定。
expression
是一个表达式,用于计算并返回函数的结果。
# 输出: Hello, world!
f = lambda: "Hello, world!"
print(f())
'''
输出结果为:
Hello, world!
'''
# 设置一个函数参数 a,函数计算参数 a 加 10
x = lambda a : a + 10
print(x(5))
'''
输出结果为:
5
'''
# 按照条件给字典数据排序
datas = [
{
"name": "臭小宇",
"age": 21
},
{
"name": "茜茜",
"age": 19
}
]
def my_max(items=None, f=lambda e: e["age"]):
if items is None:
items = datas
max_age = 0
max_da = None
for d in items:
if f(d) > max_age:
max_age = f(d)
max_da = d
print(max_da)
my_max()
'''
输出结果为:
{'name': '臭小宇', 'age': 21}
'''
4.闭包
在 Python 中,闭包(Closure)是指能够在其作用域之外访问定义时的自由变量的函数。换句话说,闭包是一个函数,它不仅仅是自身的函数体,还包含了定义时作用域内的变量的引用。理解闭包有助于实现更灵活和强大的函数设计。
通常来讲,闭包有三个特点:函数嵌套,内部函数可以访问外部函数的变量,外部函数返回内部函数。
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
# 创建闭包
closure = outer_function(10)
# 调用闭包
result = closure(5)
print(result) # 输出 15
'''
outer_function 是外部函数,它接受一个参数 x。
inner_function 是内部函数,它接受参数 y,并返回 x + y 的结果。
outer_function 返回 inner_function,这时 x 的值是 10。
我们将 outer_function(10) 的返回值赋给 closure,这个 closure 就是一个闭包,它包含了 x 的值为 10。
我们调用 closure(5),实际上是在调用 inner_function,这时 x 是闭包中的 10,所以结果为 10 + 5 = 15。
'''
闭包在编程中有多种实际应用,其中包括:
- 封装:闭包可以将函数与其环境(定义时的变量)捆绑在一起,形成一个封闭的单元,避免全局变量的污染。
- 回调函数:常用于事件处理和异步编程中,可以捕获并记住状态。
- 延迟计算:通过将参数绑定在闭包中,在需要的时候进行计算,而不是立即执行。
在使用闭包时,需要注意:
- 内存管理:因为闭包保留了外部函数的环境,所以可能会导致内存占用问题,特别是当闭包的作用域很大或者存在循环引用时。
- 变量的绑定时间:闭包中的自由变量在定义时就已经绑定,而不是在调用时。
5.装饰器
装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。
装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。
装饰器的语法使用 @decorator_name 来应用在函数或方法上。
Python 装饰允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。
def decorator_function(original_function):
def wrapper(*args, **kwargs):
# 这里是在调用原始函数前添加的新功能
before_call_code()
result = original_function(*args, **kwargs)
# 这里是在调用原始函数后添加的新功能
after_call_code()
return result
return wrapper
# 使用装饰器
@decorator_function
def target_function(arg1, arg2):
pass # 原始函数的实现
'''
decorator 是一个装饰器函数,它接受一个函数 func 作为参数,
并返回一个内部函数 wrapper,在 wrapper 函数内部,你可以执行一些额外的操作,
然后调用原始函数 func,并返回其结果。
decorator_function 是装饰器,它接收一个函数 original_function 作为参数。
wrapper 是内部函数,它是实际会被调用的新函数,它包裹了原始函数的调用,
并在其前后增加了额外的行为。
当我们使用 @decorator_function 前缀在 target_function 定义前,
Python会自动将 target_function 作为参数传递给 decorator_function,
然后将返回的 wrapper 函数替换掉原来的 target_function。
'''
装饰器通过 @ 符号应用在函数定义之前
@time_logger
def target_function():
pass
# 等同于
def target_function():
pass
target_function = time_logger(target_function)
这会将 target_function 函数传递给 decorator 装饰器,并将返回的函数重新赋值给 target_function。从而,每次调用 target_function 时,实际上是调用了经过装饰器处理后的函数。
通过装饰器,开发者可以在保持代码整洁的同时,灵活且高效地扩展程序的功能。
装饰器函数也可以接受参数
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
'''
以上代码中 repeat 函数是一个带参数的装饰器,它接受一个整数参数 n,
然后返回一个装饰器函数。该装饰器函数内部定义了 wrapper 函数,
在调用原始函数之前重复执行 n 次。
因此,greet 函数在被 @repeat(3) 装饰后,会打印三次问候语。
'''
装饰器的应用场景:
- 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
- 性能分析: 可以使用装饰器来测量函数的执行时间。
- 权限控制: 装饰器可用于限制对某些函数的访问权限。
- 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。
通过装饰器,可以将这些横切关注点(cross-cutting concerns)从业务逻辑中分离出来,使得代码更加模块化、易于维护和扩展。
标签:function,10,函数,Python,作用域,print,def From: https://blog.csdn.net/2402_86120726/article/details/140557762