【问题标题】:Scoping problems with decorators in inheritance继承中装饰器的范围问题
【发布时间】:2014-07-30 16:06:44
【问题描述】:

我正在尝试检查一个类是否能够通过装饰器拥有一个文件,使用下面的代码我发现即使子类CSVStorageHandler 调用其父类的checkIfNoStorageHandler,变量func 已超出范围。

这有点令人困惑,有人可以帮忙吗?

class StorageHandler(object):
    def __init__(self):
        self.output_file = self.openFile()

    def checkIfNoStorageHandler(func):
        def createFileByStorageHandler(self, *args, **kwargs):
            print func
            if self.__class__.__name__ == "CSVStorageHandler":
                return self.func()
            else:
                print ("class " + self.__class__.__name__ + " don't store file by default")
                return None
        return createFileByStorageHandler

    @checkIfNoStorageHandler    
    def openFile(self):
        return open('./log.txt', 'w')

class CSVStorageHandler(StorageHandler):
    def doNothing(self):
        pass
class NoStorageHandler(StorageHandler):
    def doNothing(self):
        pass


test = CSVStorageHandler()

错误信息

Traceback (most recent call last):
  File "tset_decorator_inheritance.py", line 27, in <module>
    test = CSVStorageHandler()
  File "tset_decorator_inheritance.py", line 3, in __init__
    self.output_file = self.openFile()
  File "tset_decorator_inheritance.py", line 9, in createFileByStorageHandler
    return self.func()
AttributeError: 'CSVStorageHandler' object has no attribute 'func'

【问题讨论】:

  • 我看不到您将func 属性分配给StorageHandler 或其任何子项的任何地方。因此,该错误消息完全有意义。它与范围界定无关。你是不是只想做return func() 而不是return self.func()
  • 感谢您的建议,但 func()openFile(self) ,我需要 self.func() 才能正确调用
  • 见下面@Eevee 的回答。

标签: python inheritance decorator


【解决方案1】:

self.func() 是一个勇敢的尝试,但不起作用,因为点语法永远不会关心名为 func 的本地名称。

您要确保函数接收到self,所以只需将其传入即可。

return func(self, *args, **kwargs)

【讨论】:

  • 感谢您的回答,它起作用了,但是 self.func()func(self) 之间有什么区别,这不完全一样吗,你们都只是将 self 传递给函数?
  • 没有; self.func()self 上查找 func 作为方法。 func(self)self 传递给名为 func 的本地或全局函数。 self.func() 最终会通过 self,是的,但它所做的主要工作是首先找到函数
【解决方案2】:

func 在范围内,但您的代码正在尝试访问 self.func。也许您的意思是在第 9 行使用func() 而不是self.func()

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 2018-04-17
    相关资源
    最近更新 更多