嵌套Python类需要访问封闭类中的变量

嵌套Python类需要访问封闭类中的变量,python,scope,nested-class,Python,Scope,Nested Class,我已经看到了一些“解决方案”,但每次的解决方案似乎都是“不要使用嵌套类,在外部定义类,然后正常使用它们”。我不喜欢这个答案,因为它忽略了我选择嵌套类的主要原因,也就是说,所有创建的子类实例都可以访问一个常量池(与基类关联) 下面是示例代码: class ParentClass: constant_pool = [] children = [] def __init__(self, stream): self.constant_pool = Consta

我已经看到了一些“解决方案”,但每次的解决方案似乎都是“不要使用嵌套类,在外部定义类,然后正常使用它们”。我不喜欢这个答案,因为它忽略了我选择嵌套类的主要原因,也就是说,所有创建的子类实例都可以访问一个常量池(与基类关联)

下面是示例代码:

class ParentClass:

    constant_pool = []
    children = []

    def __init__(self, stream):
        self.constant_pool = ConstantPool(stream)
        child_count = stream.read_ui16()
        for i in range(0, child_count):
            children.append(ChildClass(stream))

    class ChildClass:

        name = None

        def __init__(self, stream):
            idx = stream.read_ui16()
            self.name = constant_pool[idx]
所有类都传递一个参数,该参数是一个自定义位流类。我的目的是提供一种解决方案,它不需要我在仍然处于父类中时读取ChildClass的idx值。所有子类流读取都应该在子类中完成

这个例子过于简化了。常量池不是我需要的所有子类都可用的唯一变量。idx变量不是从流读取器读取的唯一内容

这在python中可能吗?没有办法访问家长的信息吗?

好吧,下面的工作(从您的示例中进一步简化)。请注意,您不必在类级别“声明”成员变量,如C++/C#/Java等,只需在
\uuu init\uu
内将它们设置为
self

class ParentClass:
    def __init__(self):
        self.constant_pool = ["test"]
        self.ChildClass.constant_pool = self.constant_pool
        self.children = [self.ChildClass()]

    class ChildClass:
        def __init__(self):
            self.name = self.constant_pool[0]
            print "child name is", self.name

p = ParentClass() # Prints "child name is test"

请注意,您仍然可以在不嵌套子类的情况下执行相同的操作。

您可以通过父类的名称访问父类:

class ChildClass:

    name = None

    def __init__(self, stream):
        idx = stream.read_ui16()
        self.name = ParentClass.constant_pool[idx]

再说一次,我不确定我是否理解您想要实现的目标。

这里不需要两门课。下面是以更简洁的方式编写的示例代码

class ChildClass:
    def __init__(self, stream):
        idx = stream.read_ui16()
        self.name = self.constant_pool[idx]

def makeChildren(stream):
    ChildClass.constant_pool = ConstantPool(stream)
    return [ChildClass(stream) for i in range(stream.read_ui16())]

欢迎使用Python。类在运行时是可变的。享受。

你的问题使用了subclass这个词,所以我用它来解释你的问题。和其他回答的人一样,我不确定我是否理解你在寻找什么

class ParentClass(object):
  constant_pool = [c1, c2, c3]
  def __init__(self):
    # anything not included in your question

class ChildClass(ParentClass):
  def __init__(self, stream):
    ParentClass.__init__(self)
    self.name = ParentClass.constant_pool[stream.read_ui16()]

stream = get_new_stream()
children = []
for count in range(stream.read_ui16()):
  children.append(ChildClass(stream))
此代码使用继承从父类(以及所有方法等)派生子类。常量池是父类本身的一个属性,尽管可以将其视为父类或子类的任何实例的属性(在
ChildClass中称为
self.constant\u pool
。\uuuu init\uuuu
将等同于上述内容,但在我看来,这是误导性的)

嵌套类定义不是必需的。在ParentClass中嵌套ChildClass的定义仅仅意味着ChildClass是ParentClass的一个属性,仅此而已。它不会让ChildClass的实例从父类继承任何东西。

尽管我的评论“有点高人一等”(称之为公平竞争!),但实际上有一些方法可以实现您想要的:不同的继承途径。一对夫妇:

  • 编写一个decorator,在类声明后立即对其进行内省,查找内部类,并将外部类的属性复制到它们中

  • 对元类执行相同的操作

  • 这里是decorator方法,因为它是最简单的:

    def matryoshka(cls):
    
        # get types of classes
        class classtypes:
            pass
        classtypes = (type, type(classtypes))
    
        # get names of all public names in outer class
        directory = [n for n in dir(cls) if not n.startswith("_")]
    
        # get names of all non-callable attributes of outer class
        attributes = [n for n in directory if not callable(getattr(cls, n))]
    
        # get names of all inner classes
        innerclasses = [n for n in directory if isinstance(getattr(cls, n), classtypes)]
    
        # copy attributes from outer to inner classes (don't overwrite)
        for c in innerclasses:
            c = getattr(cls, c)
            for a in attributes:
                if not hasattr(c, a):
                    setattr(c, a, getattr(cls, a))
    
        return cls
    
    以下是其使用的一个简单示例:

    @matryoshka
    class outer(object):
    
        answer = 42
    
        class inner(object):
    
            def __call__(self):
                print self.answer
    
    outer.inner()()   # 42
    

    然而,我忍不住认为其他答案中建议的一些想法会更好地为您服务。

    另一种可供考虑的设计方案:

    当您发现自己试图使用类作为名称空间时,将内部类放入它们自己的模块中并确定外部类全局变量的属性可能更有意义。换句话说,如果您从未打算实例化您的
    父类
    ,那么它只是作为一个美化的模块


    全局变量在大多数编程语言中都很糟糕,但在Python中它们并不是真正的全局变量,并且被很好地封装到模块中。

    我使用的实际类有20个子对象和5个“共享”资源,因此当我将每个共享资源应用到每个对象时,这个解决方案将产生100行赋值。这正是我试图通过实现父/子关系来避免的黑客行为的类型。也是列表理解吗?你似乎想给这个家伙留下深刻印象。使用Python而不使用理解就像去坎昆而不去海滩。你的装饰师建议正是我想要的。我最终得到了以下结果,这在我工作的情况下实现了我想要的结果[我无法理解注释中的代码格式是如何工作的,我放弃]:
    def add_parent_links(cls):cls_init=cls.\uu init_uu_u_uinit_u(self,s):对于k in dir(self):if str(type)(getattr(self,k)).find('classobj')>-1:getattr(self,k).parent=self-cls\u init(self,s)cls.\uuuuu init\uuuuu=\uuuuuu init\uuuuuuuu返回cls
    对于一个变量,在基类frmo的“类范围”中命名geting,请参阅-unansweredWell我对python还是有点陌生,但是将常量池作为一个全局变量会起作用吗?调用它们
    ParentClass
    ChildClass
    不会使它们成为父类和子类asses.内部类与其封闭类没有继承关系。唯一的方法是让
    ParentClass
    自我反省,并向其每个子类提供对自身的引用。“将它们称为ParentClass和ChildClass并不会使它们成为父类和子类。”有点自命不凡,并且假设我这样命名它们不仅仅是为了让人们阅读代码并试图理解我在做什么。这行有必要吗?你真的不明白我这样命名它们的动机吗?我想他想说的是嵌套类不共享父/子关系ip,不管程序员的意图如何。您选择的名称预先假定这种关系是可行的,这正是他想要纠正的。我同意ironchefpython的观点。在ParentClass中嵌套ChildClass不会改变ChildClass的行为。这只意味着您的代码必须通过调用ParentCla来创建实例ss.ChildClass(流)代替JU