既然我了解了您的设计,那么您做的事情都错了。
首先,Outer 是一个类;它没有得到__call__
编辑。您的第 17 行只是要构造一个空Outer
对象并且什么都不做。如果您想“调用”该Outer
对象,您可以定义一个__init__
方法——或者,正如 Sheena 所建议的,定义 a__new__
并拦截初始化,因为您实际上并不需要初始化的对象。
老实说,我不认为那些还不了解如何__call__
工作的人应该尝试构建像这样棘手的东西。但是,如果您坚持,请继续阅读。
在一个类而不是一个实例中收集这种东西是一个非常奇怪,并且可能很糟糕的设计。请记住,类变量实际上是全局变量,包含所有这些。如果您尝试以Outer
可重入方式使用,或者从多个线程/事件处理程序/greenlets/whatever 中使用,那么这些用途最终会相互踩踏。即使您认为现在这可能不会成为问题,但它可能会在未来的某个时候成为问题。
您可以创建一个Outer
实例,并将其成员用作装饰器。例如:
from outer_library import Outer
outer = Outer()
@outer.get("/")
…
但我不确定那会好得多。这里的整个设计似乎涉及在模块级别执行操作,即使看起来您只是定义普通函数并在最后调用一个函数。您设法使自己感到困惑的事实应该证明这是多么令人困惑的设计。
但是,如果您确实想要这样做,您可能想要做的是在Outer.__init__
方法中定义类,并将它们分配给实例成员。类是一等值,可以像任何其他值一样分配给变量。然后,使用这些类的__init__
(或__new__
)方法来完成您想要的工作,使这些类模拟函数。
这可能看起来令人困惑或误导。但是请记住,您尝试做的全部重点是以一种看起来像方法的方式使用类,因此这种混淆是问题固有的。但是,如果您愿意,可以将装饰器编写为函数(在这种情况下,作为 的普通实例方法Outer
);它只是使问题的不同部分变得更难,而不是这部分。
设计这样的东西的一种更正常的方法是创建Outer
一个完全正常的类,人们可以对其进行子类化或创建实例,并提供一种显式的非花哨方式来将处理程序方法或函数附加到 URL。然后,一旦它起作用,设计一种方法来简化使用装饰器注册的处理程序。