2012-12-10 66 views
1

我有这种情况下,我需要问一个嵌套类将附加项添加到外部类中的列表。继承人伪代码,这与我试图做的相似。我将如何去实现它的工作?在嵌套类中,如何从Python中的嵌套类访问外部类的元素?

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版

+4

为什么要使用一个嵌套类*在所有*? –

+0

因此,我试图让Outer类包含将接受参数的装饰器,最好的方法是将装饰器写成类http://stackoverflow.com/questions/10610824/python-shortcut-for-writing- decorator-which-accept-arguments – sri

+2

是的,使用装饰器的类是一个好主意,但这并不意味着你需要使用* nested *类。你想要解决什么问题? –

回答

2

现在,我了解你的设计,你会发现一切都是错误的。

首先,Outer是一类;它没有得到__call__版。你的第17行正要构造一个空的Outer对象,并且什么也不做。如果你想“呼叫”对象,你可以定义一个__init__方法,或者,正如Sheena所建议的那样,定义一个__new__并拦截初始化,因为你实际上并不需要初始化对象。

老实说,我不认为有人不明白__call__是如何工作的,但应该尝试构建一些棘手的问题。但如果你坚持,请继续阅读。

这是一个非常奇怪的,也许是坏的设计,收集这种类的东西在类而不是一个实例。请记住,类变量实际上是全局变量,包含所有这些变量。如果你尝试使用Outer或者从多个线程/事件处理程序/ greenlet /无论如何,这些使用将最终彼此跺脚。即使你认为现在不会成为问题,它可能会在未来某个时候。

您可以创建一个Outer实例,并将其成员用作装饰器。例如:

from outer_library import Outer 

outer = Outer() 

@outer.get("/") 
… 

但我不确定那会好很多。这里的整个设计似乎涉及在模块级别执行操作,即使看起来您只是定义普通函数并在最后调用函数。你设法混淆自己的事实应该是这种设计有多混淆的证据。

但如果你想要做到这一点,你可能想要做的是定义Outer.__init__方法内的类,并将它们分配给实例成员。类是一流的值,可以像任何其他值一样分配给变量。然后,使用这些类的__init__(或__new__)方法来完成你想要的工作,使这些类模拟函数。

这似乎令人困惑或误导。但请记住,你所要做的全部事情就是以一种看起来像一种方法的方式使用一个类,这样就会产生这种混淆。但是,如果你愿意,你可以编写装饰器作为函数(在这种情况下,作为Outer的常规实例方法);它只是使问题的一个不同部分,而不是这部分。

设计类似这样东西的一种更常见的方式是使Outer成为一个完全正常的类,人们可以创建子类或创建实例,并提供一种明确的非奇妙方式来将处理函数方法或函数附加到URL。然后,一旦工作,设计一种方法来简化处理程序注册与装饰器。

+0

采取了点。 (在''__main__''部分pastebin代码是错误的 - 我的不好,)我不应该在网上讨论我的项目atm,但可以说,它应该是一个singleton,应该可以调用,它是在我的代码中正确实例化。对不起,关于不能说清楚的事情,下次我会继续努力。但至少在我的问题得到回答之后。谢谢。 :) – sri

4

您只能使用完整全局名称来访问外部类:

class Outer(object): 
    outerlist = [] 
    class Inner(object): 
     def __call__(self, arg1): 
      Outer.outerlist.append(arg1) 

在python中,通常不需要在任何情况下嵌套类。有一些用例可以在函数中定义一个类(使用范围变量),但很少需要嵌套类。

+0

这大部分都是正确的,但是使用'__call__'意味着你必须编写'Outer.Inner()(“apple”)'而不是'Outer.Inner(“apple”)''。错误在于OP的代码中,而不是你的代码,但它仍然需要纠正。 – abarnert

+0

@abarnert:OP几乎不知道需要实现什么,所以我会推迟谈论如何调用这个,直到它清楚真正的目标是什么。 –

+0

@MartijnPieters对不起。我手中有一只不安分的宠物 - 由于延误,这涉及家庭作业 - 因此模糊。我在这个问题下回复了你的评论。请检查。我会很乐意进一步解释。谢谢。 – sri

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 
+0

每次调用__init__或'__call__''时都调用__new__吗?这很漂亮。 – sri

+0

@sri:不是每次它做一个'__call__' - 这是一个实例方法,可以多次调用。它被调用一次,当类需要创建一个实例时 - 通常是在'__init__'之前。 – abarnert

+1

@Sheena:他们是“类变量”。 “静态”这个词是指与类和实例都不相关的东西,而“属性”是一种特殊的类变量,其描述符让它们像一个实例变量一样工作。但否则,所有的钱。 – abarnert

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 
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()