在嵌套类中,如何访问外部类';从Python中的嵌套类中删除元素?

在嵌套类中,如何访问外部类';从Python中的嵌套类中删除元素?,python,class,nested,Python,Class,Nested,我有这样一个场景,我需要要求嵌套类将项附加到外部类中的列表中。这是一个伪代码,和我想做的很相似。我怎样才能让它工作呢 class Outer(object): outerlist = [] class Inner(object): def __call__(self, arg1): outerlist.append(arg1) if __name__ == "__main__": f = Outer() f.Inner("apple") f.Inner(

我有这样一个场景,我需要要求嵌套类将项附加到外部类中的列表中。这是一个伪代码,和我想做的很相似。我怎样才能让它工作呢

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

您只能使用全局全名访问外部类:

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

在python中,在任何情况下通常都不需要嵌套类。在某些用例中,在函数中定义类(使用作用域变量)是有意义的,但很少需要嵌套类。

这将产生预期的结果

请注意
\uuuu new\uuuu
(第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

既然我了解了你的设计,你就大错特错了

首先,外部是一个类;它不会被调用。您的第17行只会构造一个空的
外部
对象,而不使用它。如果要“调用”外部对象,可以定义一个
\uuuuu init\uuuu
方法,或者,正如Sheena所建议的,定义一个
\uuu new\uuuuu
并拦截初始化,因为实际上并不需要初始化的对象

老实说,我不认为一个不了解
\uuuu call\uuuu
如何工作的人应该尝试构建类似这样的复杂东西。但如果你坚持,请继续读下去

在类中而不是在实例中收集此类内容是一种非常奇怪的设计,可能很糟糕。请记住,类变量实际上是全局变量,包含所有这些变量。如果您尝试以可重入方式使用
Outer
,或者从多个线程/事件处理程序/greenlets/任何东西中使用,那么这些用法最终都会互相践踏。即使你认为现在这不可能成为一个问题,但在将来的某个时候它可能会成为一个问题

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

from outer_library import Outer

outer = Outer()

@outer.get("/")
…
但我不确定这是否更好。这里的整个设计似乎涉及到在模块级别执行操作,尽管看起来您只是在定义普通函数并在最后调用函数。事实上,你已经设法使自己困惑,这应该是一个多么令人困惑的设计证据

但是如果您确实想这样做,您可能想做的是在
Outer.\uuuu init\uuu
方法中定义类,并将它们分配给实例成员。类是一级值,可以像其他值一样分配给变量。然后,使用这些类的
\uuuuu init\uuuuu
(或
\uuuu new\uuuuuu
)方法来完成所需的工作,使这些类模拟函数

这似乎令人困惑或误导。但是请记住,您试图做的全部工作是以一种看起来像方法的方式使用一个类,因此这种混淆是问题固有的。但是如果您愿意,您可以将decorator编写为函数(在本例中,作为
Outer
的普通实例方法);这只会让问题的另一部分变得更难,而不是这一部分


设计这样的东西的一种更普通的方法是将
Outer
制作成一个完全正常的类,人们可以对其进行子类化或创建实例,并提供一种显式的非奇特的方式将处理程序方法或函数附加到URL。然后,一旦这起作用,设计一种方法来简化与装饰器的处理程序注册。

为什么不将外部类实例作为参数传递给内部类方法?您可以通过这种方式访问外部类实例的成员

  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

我认为picmate指出的选项(将外部类作为内部类的输入传递)对于这个特定问题是一个很好的选择。请注意,它也可以在不必“嵌套”类的情况下工作(在我看来,这里要避免一些事情,因为它是不必要的)。注意,我还将内部类的初始化嵌入到外部类中(这一步不是严格需要的,但我在这里包括它是为了说明):


为什么要使用嵌套类呢?所以我尝试让外部类包含接受参数的装饰器,最好的方法是将装饰器编写为类是的,使用类作为装饰器是个好主意,但这并不意味着需要使用嵌套类。你想解决什么问题?@sri:是的,我同意,装饰师应该是一个职业。但是你装饰的类应该是一个完全独立的类。没有嵌套。一些次要问题:我假设您想要打印f.outerlist,而不是
f.outerlist()
,因为您无法调用
列表。此外,虽然您可以通过实例访问类变量,但通过类访问它们通常不会太混乱,如
print Outer.outerlist
。(事实上,您通过
f
访问它意味着我必须问:
\uuuuuu new\uuuuu
每次调用
\uuu init\uuuuu
\uu调用
时都会调用它吗?)?这很好。@sri:不是每次它都执行一个
\uuuuu调用\uuuuu
——这是一个实例方法,可以多次调用。当类通常需要创建实例时,在
\uuuu init\uuu
@Sheena之前调用一次:它们是“类变量”。“static”一词指的是既不与类也不与实例相关联的事物,“properties”是一种特殊的类变量,其描述符使它们的行为类似于实例变量。但除此之外,一切都在钱上。这主要是r
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()