You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中能否在装饰器内调用被装饰函数?及需求实现问询

问题与解决方案

需求说明

获取用户输入,仅当输入为5时才执行目标函数(如翻倍操作);若用户输入其他数字,装饰器需提示数字不是5并重新请求输入,直到用户输入5为止。

尝试的代码与问题

第一次尝试

代码:

def check_five(func):
    def wrapper(*args,**kwargs):
        if args==(5,):
            return func(*args)
        else:
            print("Numbers is not 5.")
            return func(int(input("Enter a: ")))
    return wrapper


@check_five
def double(a):
    return a+a

print(double(int(input("Enter a: "))))

问题:首次输入非5时会提示并重新输入,但第二次输入任意数字都会直接执行目标函数,无法持续验证直到输入5。

第二次尝试

代码:

def check_five(func):
    def wrapper(*args,**kwargs):
        if args==(5,):
            return func(*args)
        else:
            print("Numbers is not 5.")
            return double(int(input("Enter a: ")))
    return wrapper


@check_five
def double(a):
    return a+a

print(double(int(input("Enter a: "))))

问题:能正常工作,但装饰器内硬编码了目标函数名double,导致装饰器无法复用在其他函数上,违背了装饰器的设计初衷。

疑问

  1. 是否存在其他仅使用装饰器就能实现需求的方法?
  2. Python中能否在装饰器内调用被装饰函数?

解答

关于装饰器内调用被装饰函数

完全可以,这是装饰器的常规用法之一。比如日志装饰器中,会先调用原函数获取返回值,再记录日志。但要注意不能像第二次尝试那样硬编码函数名,应该使用闭包中捕获的func变量(也就是装饰器参数里的原函数引用),这样装饰器才能复用在任意函数上。

正确的实现方式

核心思路是在装饰器的wrapper函数中加入循环逻辑,持续验证输入直到符合条件,再调用原函数:

def check_five(func):
    def wrapper(*args, **kwargs):
        # 获取初始传入的参数
        num = args[0] if args else kwargs.get('a')
        # 循环验证,直到输入为5
        while num != 5:
            print("数字不是5。")
            num = int(input("Enter a: "))
        # 符合条件后调用原函数
        return func(num)
    return wrapper

@check_five
def double(a):
    return a + a

# 测试
print(double(int(input("Enter a: "))))

复用性验证

这个装饰器可以直接复用在其他函数上,比如实现三倍运算:

@check_five
def triple(a):
    return a * 3

# 测试
print(triple(int(input("Enter a: "))))

运行后同样会持续要求输入直到输入5,然后执行三倍运算,说明装饰器的复用性正常。

总结

  • 装饰器内调用被装饰函数是合法且推荐的,关键是使用闭包捕获的func变量,避免硬编码函数名。
  • 通过在wrapper中加入循环逻辑,可以实现持续验证输入直到符合条件的需求,同时保证装饰器的复用性。

内容的提问来源于stack exchange,提问作者Yogesh Rakate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:26:30