我有这种情况,我需要让嵌套类将项目附加到外部类的列表中。 Heres伪代码类似于我想要做的事情。我怎么去开始工作?
class Outer(object):
outerlist = []
class Inner(object):
def __call__(self, arg1):
outerlist.append(arg1)
if __name__ == "__main__":
f = Outer()
f.Inner("apple")
f.Inner("orange")
print f.outerlist()
我希望看到这一点 - apple, orange
详细说明:
OS X,Python 2.7
答案 0 :(得分:4)
您只能使用完整的全局名称访问外部类:
class Outer(object):
outerlist = []
class Inner(object):
def __call__(self, arg1):
Outer.outerlist.append(arg1)
在python中,通常不需要在任何情况下嵌套类。有一些用例,在函数中定义一个类是有意义的(使用作用域的变量),但很少需要嵌套类。
答案 1 :(得分:2)
这将产生预期的结果。
注意使用__new__
(A行)。这意味着内部只需附加列表,而不是正确地进行任何构造。此外,要访问包含类的类属性,只需使用外部类的名称(第B行)。
最后看到第C行。列表不是函数。您的原始代码中有一些额外的括号。
class Outer(object):
outerlist = []
class Inner(object):
def __new__(self, arg1): #A
Outer.outerlist.append(arg1) #B
f = Outer()
f.Inner("apple")
f.Inner("orange")
print f.outerlist #C
答案 2 :(得分:2)
既然我理解了你的设计,你就会发生错误。
首先,外面是一个阶级;它没有得到__call__
。你的第17行只是构造一个空的Outer
对象而不对它做任何事情。如果你想“调用”Outer
对象,你可以定义一个__init__
方法 - 或者像Sheena建议的那样,定义一个__new__
并拦截初始化,因为你实际上并没有无论如何都需要初始化的对象。
老实说,我认为不理解__call__
如何运作的人应该尝试构建一些像这样棘手的东西。但如果你坚持,请继续阅读。
在类中而不是实例中收集这类东西是一种非常奇怪的,可能很糟糕的设计。请记住,类变量实际上是全局变量,所有这些都需要。如果你尝试重新使用Outer
,或者从多个线程/事件处理程序/ greenlets /中使用,那么这些用法最终会相互踩踏。即使你认为现在不太可能成为一个问题,它可能会在未来的某个时候出现。
您可以创建一个Outer
实例,并将其成员用作装饰器。例如:
from outer_library import Outer
outer = Outer()
@outer.get("/")
…
但我不确定那会好得多。这里的整个设计似乎涉及在模块级执行操作,即使看起来你只是定义了正常的函数并在最后调用了一个函数。你设法让自己迷惑的事实应该证明这是一个令人困惑的设计。
但是如果您做想要这样做,您可能想要做的是在Outer.__init__
方法中定义类,并将它们分配给实例成员。类是一等值,可以像任何其他值一样分配给变量。然后,使用这些类的__init__
(或__new__
)方法完成您想要的工作,使类模拟函数。
这可能看起来令人困惑或误导。但要记住,你要做的事情的重点在于以一种看起来像方法的方式使用一个类,因此这种混淆是问题所固有的。但如果您愿意,可以将装饰器编写为函数(在本例中,作为Outer
的常规实例方法);它只是使问题的另一部分变得更难而不是这部分。
设计类似这样的东西的更常规的方法是使Outer
成为一个完全正常的类,人们可以将其子类化或创建实例,并提供一种明确的非奇特方式来将处理程序方法或函数附加到网址。然后,一旦它工作,设计一种方法来简化装饰器注册处理程序。
答案 3 :(得分:0)
为什么不将外部类实例作为参数传递给内部类方法?您可以通过这种方式访问外部类实例的成员。
class Outer(object):
outerlist = []
class Inner(object):
def __init__(self, outer_self):
self.outer = outer_self
def __call__(self, arg1):
self.outer.outerlist.append(arg1)
if __name__ == "__main__":
f = Outer()
i = f.Inner(f)
i("apple")
i("orange")
print f.outerlist
答案 4 :(得分:0)
我认为picmate指出的选项(将外部类作为内部类的输入)是这个特定问题的一个很好的选择。请注意,它也可以工作,而不必嵌套'这些课程(在我看来,由于不必要,所以要避免这种情况)。请注意,我还在内部类中嵌入了内部类的初始化(这一步不是严格需要的,但我将其包含在此处用于说明目的):
class Outer(object):
outerlist = []
def __init__(self):
self.Inner=Inner(Outer=self)
def get_basket(self):
print "Outer basket: %s" %(self.outerlist)
class Inner(object):
def __init__(self,Outer):
self.Outer=Outer
def __call__(self, arg1):
self.Outer.outerlist.append(arg1)
def get_basket(self):
print "Inner basket: %s" %(self.Outer.outerlist)
if __name__ == "__main__":
f = Outer()
print "Initial state"
f.get_basket()
f.Inner.get_basket()
f.Inner("apple")
f.Inner("orange")
print "Final state"
f.get_basket()
f.Inner.get_basket()