调用被装饰函数时,装饰器返回的函数没有被执行。我错过了一些明显的东西吗?

问题描述 投票:0回答:1

我尝试编写一个小函数,以便更轻松地创建带有参数的装饰器:

def decoratorAddSupportForOptionalArguments(addToDict: typing.Callable):
    """Takes a function with arguments, where the first argument is callable and returns a modified version that enables decorator like syntax.
    """
    def addToDictDecorator(*argumentsPassedTo_addToDict, **kargumentsPassedTo_addToDict):
        kargumentsPassedTo_addToDict_keys = kargumentsPassedTo_addToDict.keys()
        if len(argumentsPassedTo_addToDict) == 1 and callable(argumentsPassedTo_addToDict[0]) and 0==len(kargumentsPassedTo_addToDict_keys):
            returnVal= addToDict(argumentsPassedTo_addToDict[0])
            return returnVal if returnVal!=None else addToDict
        # addToDict is being called as a function
        def decFinal(func):
            returnVal = addToDict(func,*argumentsPassedTo_addToDict, **kargumentsPassedTo_addToDict)
            print(f"decFinal {func.__name__} {returnVal}")
            return returnVal if returnVal!=None else addToDict
        return decFinal
    return addToDictDecorator

应该按以下方式使用:


myDict=dict()
import random
@decoratorAddSupportForOptionalArguments
def addToDict(func, key=None, log=None):
    print("addToDict")
    myDict[key if key else str(random.random())]=func
    def wrapper(*args, **kwargs): # @note This is supposed to be called every time the decorated function gets called.
        print("foo")              # It never gets called however - and I cant figure out whats wrong
        if log:
            print(log)
        func(*args,**kwargs)
    return wrapper

@addToDict
def isValid(value):
    return value != None
@addToDict("myFancyKey")
def isPrivate(value):
    return value.__name__.startswith("_")
@addToDict()
def printRandom(value):
    print(random.random())
@addToDict("notepad",log="Starting notepad")
def startNotepad():
    import os
    print("notepad")
    os.system("notepad.exe")
print(myDict)
myDict["notepad"]()
myDict["notepad"]()
myDict["notepad"]()

每次我尝试执行任何以

addToDict
为前缀的函数时,“decFinal”都会按预期执行,但它的返回值(在我的示例中是
wrapper
内部的
addToDict
永远不会被调用。据我了解,
@
装饰器语法应该执行装饰器返回的任何函数。有人可以帮我发现我在这里缺少什么吗?😅 每次
startNotepad
被执行时,我希望看到
wrapper
中的“foo”打印出来了。

编辑:有趣的是,当我尝试调用“isValid”时,“foo”确实会被打印,该“isValid”是用

@addToDict
声明的,不带括号(与
startNotepad
不同)。只是,在这两种情况下,逻辑基本上做了相同的事情,除了 startNotepad 首先需要在 foo 最终被调用之前调用
decFinal

python logic python-decorators
1个回答
0
投票

您的问题是您将 func 添加到字典中,而不是包装版本中。所以只有

startNotepad()
实际上打印 foo - 因为它是装饰版本,而不是
myDict['notepad']()
- 因为它是原始函数

所以代替这个:

def addToDict(func, key=None, log=None):
    print("addToDict")
    myDict[key if key else str(random.random())]=func # here, func is original undecorated version! 
    def wrapper(*args, **kwargs):
        print("foo")              
        if log:
            print(log)
        func(*args,**kwargs)
    return wrapper

你必须添加包装纸。所以该行必须位于本地函数下方:

def addToDict(func, key=None, log=None):
    def wrapper(*args, **kwargs):
        print("foo")              
        if log:
            print(log)
        func(*args,**kwargs)
    print("addToDict")
    myDict[key if key else str(random.random())]=wrapper # fixed!  
    return wrapper
© www.soinside.com 2019 - 2024. All rights reserved.