I had a go at writing a little function for making it easier to create decorators with arguments:
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
Which is supposed to be used as following:
myDict=dict()import random@decoratorAddSupportForOptionalArgumentsdef 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@addToDictdef 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"]()
Every time I attempt executing any of the functions prefixed with addToDict
, "decFinal" gets executed like intended, but its return value (which in my example is wrapper
inside of addToDict
never gets called. To my understanding, the @
decorator syntax should execute any function returned by what is returned by the decorator. What am I missing here? Every time startNotepad
gets executed, I expect to see "foo" from wrapper
get printed.
Interestingly, "foo" does get printed when I try invoking "isValid", which was declared with @addToDict
without the parenthesis (unlike startNotepad
). It's just that, the logic does basically the same thing in both cases, except startNotepad first needs to call decFinal
before foo finally gets called.