如何在运行时向装饰器传递参数?

3

我将装饰器用于项目中一些上下文管理,例如文件备份、恢复等,并尝试使用装饰器来实现这些目的。

但是我不知道如何在运行时向装饰器传递参数。

例如我的类看起来像:

class myLogFileHandler:
    def __init__(self,file):
        self.file=file
        return

    @copyAndRestoreFile(file=<how-pass-self.file-here?>)
    def performAction(**kwargs):
        """
           do something
        """

我的装饰器会是:

def copyAndRestoreFile(file):
    def dec(fn):
        def wrapper(*args,**kwargs):
            #copy file to temp...
            fn(*args,**kwargs)
            #restore file from temp...
        return wrapper
    return dec

但是,正如你所看到的,只有在创建对象时才能使用文件名。那么该如何解决这些问题呢?
我尝试了几种解决方案,效果都不错:
  1. Make the decorator without any arguments and make it look for a particular variable in the input args dictionary..

    def copyAndRestoreFile(fn):
        def dec(**kwargs,file):
            #copy file to temp...
            fn(*args,**kwargs)
            #restore file from temp...
        return dec  
    
    @copyAndRestoreFile
    def performAction(**kwargs,file=self.file):
        """
           do something
        """
    

    With this approach i cant make the decorator a generic one which can be used by any one.. Any one who uses it should have a file arg to the function that is decorated.. that is the con that i am seeing...

  2. Decorate at run-time..

    def performAction(**kwargs):
        copyAndRestoreFile(file=self.file)(self._actualActionCode)(**kwargs)
    
    def _actualActionCode(**kwargs):
        """
           do something
        """
    

有没有更好的方法来解决这个问题?


2
一种方法是将 def wrapper(*args,**kwargs): 更改为 def wrapper(self, *args,**kwargs): 并使用 self 参数来解析您的文件名。但这将使您的装饰器仅与特定类一起使用。 - Kendas
是的,我同意。如果其他类将文件名存储在其他属性名中,那么它就不起作用了.. :( - Arun Kaliraja Baskaran
第二个例子也可以在__init__中使用self.performAction = copyAndRestoreFile(file=self.file)(self._actualActionCode)来实现。 - Kendas
1个回答

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接