【问题标题】:Using decorators in classes python3在类 python3 中使用装饰器
【发布时间】:2019-05-05 11:53:22
【问题描述】:

请帮助了解如何在类中正确使用装饰器。 例如,我想在执行类之前检查变量,如果它存在使用这个变量运行类。 如何做到这一点?

我不工作的例子:

import os,sys
import requests


def checkCredentials(function):
  KEY = os.environ['KEY']
  if KEY:
    print("exist")
    return KEY
  else:
    print("nope")
    sys.exit(0)


@checkCredentials
class StartUp(object):

  def __init__(self, argument1):
    self.argument1 = argument1

  def printstr(self):
    print(self.argument1)


if __name__ == '__main__':
  start = StartUp()

我的错误:

python3.6 ./main.py 
exist
Traceback (most recent call last):
  File "./main.py", line 26, in <module>
    start = StartUp()
TypeError: 'str' object is not callable

【问题讨论】:

  • 问题是你的装饰器返回一个字符串(或None,如果KEY不存在。装饰器需要返回一个可调用对象,通常是一个小的修改(即“装饰") 传入的那个。

标签: python python-3.x decorator python-decorators


【解决方案1】:

你应该阅读更多关于装饰器的内容,也许检查PEP 3129PEP 318。以下来自前 PEP 的示例说明了类装饰器的语义:

# Solution 1: Without class decorators
class A:
  pass
A = foo(bar(A))

# Solution 2: With class decorators
@foo
@bar
class A:
  pass

这两种解决方案产生相同的结果。在Solution 1 中,函数foobar 被显式调用以修改初始类A 并生成修改后的变体。通过使用装饰器,可以更清楚地实现相同的效果:这是Solution 2

让我们将此应用于您的代码示例。你的最后一行代码是

start = StartUp()

翻译成

start = checkCredentials(StartUp)()

但是,checkCredentials 要么不返回任何内容,要么返回 str,因此是 TypeError。我不确定你想用装饰器实现什么。如果您只想测试特定环境变量是否存在,则以下装饰器可能会产生所需的效果:

def checkCredentials(cls):
  KEY = os.environ['KEY']
  if KEY:
    print("exist")
    return cls
  else:
    print("nope")
    sys.exit(0)

请注意,如果设置了环境变量(快乐的代码路径),这将从装饰器返回原始类,否则终止执行(因此无需从装饰器返回任何内容)。

【讨论】:

  • 很棒的答案!!!多谢!还有一个问题。当我执行“返回 cli”时,我可以使用参数 KEY 运行“cli”吗?
  • @KostiaSkrypnyk 你可以。 但是可能没有预期的效果。一个类装饰器应该返回一个新的类,之后可以被实例化。如果您将一个类传递给装饰器 and 构造并从装饰器返回此类的一个实例,这会破坏装饰器的预期行为。在我看来,您似乎正在尝试将 python 装饰器用于其他目的而不是其预期目的。
猜你喜欢
  • 2017-02-17
  • 2011-11-20
  • 2021-07-16
  • 2018-11-03
  • 2014-01-14
  • 2021-02-21
  • 2020-07-22
  • 2019-09-01
  • 2018-06-28
相关资源
最近更新 更多