函数使用(函数定义及调用方式、传参与返回参数、命名空间、装饰器)

本文详细介绍了Python中的函数概念,包括其作为可重用代码块的性质,如何通过def关键字创建及调用函数,以及如何在函数中添加参数。此外,还探讨了函数的返回值,利用return实现数据传递并终止代码执行。同时,文章解释了命名空间的概念,如locals()和globals()函数的区别,并重点讲解了Python装饰器的用途——在不修改原函数代码的情况下扩展功能。

一、函数是什么?

它相当于一个独立的代码块,是可以被重复使用,如果需要增加一个功能或者修改一个功能,只需要,增加或者修改函数即可。他是只有要用的时候才会运行的代码块。

二、函数的语法

函数的关键字是def,如:

def a():                   #创建函数
    print("函数")


a()                        #调用函数

也可以在括号里添加参数:

def a(name):
    print("我是函数", name)


a("小黑")

返回值:

返回值是用return来进行返回的,但是他还可以停止运行代码块,在return后面什么都不写他就会结束函数。

def a(name, age):                        #定义
    return name, age


b = a("小黑", 18)                         #调用函数,保存函数的返回值
print(b)                                 #使用

命名空间:
python使用命名空间记录变量python中的命名空间就像是一个dictkey是变量的名字,value是变量的值。

locals

内置函数locals(), 返回当前函数(方法)的局部命名空间。

globals

内置函数globals(),返回当前module的命名空间。

locals()和globals()他两有一个区别,locals是只读,globals是可以写。

装饰器:

python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

<think>我们参考了用户提供的多个引用,特别是引用[3]和引用[4]关于装饰器内部函数参数使用。 用户的问题:Python装饰器内部函数参数使用方法 我们将从以下几个方面进行解答: 1. 装饰器的基本结构(不带参数) 2. 装饰器内部函数(wrapper)如何接收被装饰函数参数 3. 带参数装饰器装饰器本身带参数)的结构 4. 使用*args和**kwargs来通用处理被装饰函数的任意参数 根据引用[3],装饰器用到了内部函数装饰器decorator将目标函数作为参数,然后定义一个内部函数wrapper,用于包装目标函数,最后返回wrapper函数。 基本结构(不带参数装饰器): ```python def decorator(func): def wrapper(*args, **kwargs): # 在调用目标函数前可以做一些事情 result = func(*args, **kwargs) # 这里调用了原函数,并入了wrapper接收到的参数 # 在调用目标函数后可以做一些事情 return result return wrapper ``` 在这个结构中,内部函数wrapper使用*args和**kwargs来接收任意数量和类型的参数,这样它就可以适用于任何被装饰的函数。 示例:一个简单的装饰器,用于打印函数名和参数 ```python def log_decorator(func): def wrapper(*args, **kwargs): print(f"调用函数 {func.__name__},参数: args={args}, kwargs={kwargs}") result = func(*args, **kwargs) print(f"函数 {func.__name__} 执行完毕") return result return wrapper @log_decorator def add(a, b): return a + b @log_decorator def greet(name, message="Hello"): print(f"{message}, {name}!") add(1, 2) # 输出调用信息和执行完毕信息 greet("Alice", message="Hi") # 同样输出 ``` 对于带参数装饰器(即装饰器本身需要参数),我们需要再嵌套一层函数,用来接收装饰器参数,并返回一个装饰器函数(即上面的decorator这样的函数)。 带参数装饰器结构: ```python def decorator_with_args(param1, param2): def actual_decorator(func): def wrapper(*args, **kwargs): # 这里可以使用装饰器参数(param1, param2) print(f"装饰器参数: {param1}, {param2}") # 在调用目标函数前做一些事情 result = func(*args, **kwargs) # 在调用目标函数后做一些事情 return result return wrapper return actual_decorator @decorator_with_args("参数1", "参数2") def my_function(x, y): return x * y ``` 当使用参数装饰器时,实际上发生了: decorator_with_args("参数1", "参数2") 返回 actual_decorator 函数 然后 actual_decorator(my_function) 返回 wrapper 函数 这样,当调用my_function时,实际上调用的是wrapper函数,而wrapper函数内部再调用原来的my_function。 在引用[4]中,我们看到一个例子,在参数列表的特定位置插入参数(通过修改args)。这展示了装饰器内部函数可以修改递给原函数参数。 示例:在装饰器中修改参数 ```python def add_line(index, line): def decorator(func): def wrapper(*args, **kwargs): # 将args转为列表,因为元组不可变 new_args = list(args) # 在指定位置插入一行 new_args.insert(index, line) # 注意:如果原函数有默认参数使用kwargs处理,这里我们只处理位置参数 return func(*new_args, **kwargs) return wrapper return decorator @add_line(1, "插入的行") def print_args(a, b, c): print(f"a={a}, b={b}, c={c}") print_args("第一行", "第三行", "第四行") # 输出:a=第一行, b=插入的行, c=第三行 注意:第四个参数没有入,因为原函数只有三个参数,所以这里会报错?我们需要调整 ``` 上面的例子中,我们试图在第二个位置(索引1)插入一个参数,但是原函数有三个参数,而我们入三个位置参数,插入一个后变成四个,所以会出错。因此,我们需要根据被装饰函数参数进行调整,或者确保插入后参数总数正确。 实际上,引用[4]中的代码片段展示了如何修改参数列表(插入参数),并且调整了参数的位置(比如将第一个参数放到最前面)。但具体如何修改参数取决于装饰器的目的。 总结: - 装饰器内部函数(通常命名为wrapper)通过定义*args和**kwargs来接收任意参数。 - 在wrapper函数内部,我们可以修改参数(比如插入、删除、修改),然后再递给原函数(func)。 - 如果装饰器本身需要参数,则需要三层嵌套函数:最外层接收装饰器参数,中间层接收函数,内层是包装函数。 注意事项: - 使用functools.wraps装饰器可以保留原函数的元信息(如函数名、文档字符串等),这是一个好习惯。 - 修改参数时要小心,确保修改后的参数与原函数期望的参数一致。 示例:使用functools.wraps ```python from functools import wraps def log_decorator(func): @wraps(func) def wrapper(*args, **kwargs): print(f"调用函数 {func.__name__}") return func(*args, **kwargs) return wrapper ``` 相关问题: §§相关问题§§ 1. 如何用装饰器修改函数参数? 2. 带参数装饰器有什么应用场景? 3. 使用装饰器时如何保留原函数的元信息? </think>### Python装饰器内部函数参数使用方法 理解Python装饰器内部函数参数使用,关键在于**装饰器结构**和**参数递机制**。以下是核心要点及示例: --- ### 一、基本结构解析 装饰器内部函数(通常命名为`wrapper`)负责接收被装饰函数参数: ```python def decorator(func): # 接收被装饰的函数 def wrapper(*args, **kwargs): # 内部函数接收任意参数 # 装饰逻辑 result = func(*args, **kwargs) # 将参数递给原函数 return result return wrapper ``` - **`*args, **kwargs`**:通用参数接收方式,适配所有被装饰函数参数类型(位置参数、关键字参数)。 - **`func(*args, **kwargs)`**:内部函数调用函数时需显式解包参数[^3][^5]。 --- ### 二、关键用法示例 #### 1. 基础参数递 ```python def log_decorator(func): def wrapper(*args, **kwargs): print(f"调用函数: {func.__name__}, 参数: args={args}, kwargs={kwargs}") return func(*args, **kwargs) # 参数递给原函数 return wrapper @log_decorator def add(a, b): return a + b add(3, b=5) # 输出: 调用函数: add, 参数: args=(3,), kwargs={'b': 5} → 结果: 8 ``` #### 2. 修改参数 可在调用函数前修改参数: ```python def enforce_types(func): def wrapper(*args, **kwargs): # 将所有位置参数转为整数 args = [int(arg) for arg in args] kwargs = {k: int(v) for k, v in kwargs.items()} return func(*args, **kwargs) return wrapper @enforce_types def multiply(x, y): return x * y multiply("4", y="5") # 自动转整数 → 结果: 20 ``` #### 3. 带参数装饰器 装饰器本身需要参数时,需三层嵌套[^1][^4]: ```python def repeat(n): # 装饰器参数层 def actual_decorator(func): # 接收被装饰函数 def wrapper(*args, **kwargs): # 内部函数接收参数 for _ in range(n): result = func(*args, **kwargs) return result return wrapper return actual_decorator @repeat(3) def greet(name): print(f"Hello, {name}!") greet("Alice") # 输出3次: Hello, Alice! ``` --- ### 三、注意事项 1. **参数解包必须一致** `wrapper`中调用`func`时需保持`*args, **kwargs`解包,否则参数递失败[^5]。 2. **保留元信息** 使用`functools.wraps`避免丢失原函数名、文档等: ```python from functools import wraps def decorator(func): @wraps(func) # 保留原函数元信息 def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper ``` 3. **参数修改风险** 修改`args/kwargs`可能破坏原函数逻辑,需确保兼容性[^4]。 --- ### 四、核心逻辑总结 | 层级 | 作用 | 参数接收方式 | |-------------|-------------------------------|-----------------------| | 装饰器参数层 | 接收装饰器自身参数 (如`n=3`) | 常规参数 (`n`) | | 函数接收层 | 接收被装饰函数 (`func`) | 函数对象 (`func`) | | 内部函数层 | 接收被装饰函数参数 | `*args, **kwargs` | > **关键点**:内部函数通过`*args, **kwargs`捕获所有参数,并在调用`func`时解包递,实现参数透明输[^3][^5]。 --- ### 相关问题 1. 如何在装饰器中访问被装饰函数参数名? 2. 装饰器内部函数如何修改返回值? 3. 多层装饰器嵌套时参数递的顺序是怎样的? [^1]: 装饰器参数需三层嵌套结构,且参数需在导入时固定 [^3]: 内部函数`wrapper`负责包装目标函数并接收其参数 [^4]: 可通过修改`args`或`kwargs`列表改变参数 [^5]: `*args, **kwargs`确保参数递的通用性
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值