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

Ger*_*ult 11 python scope nested-class

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

这是示例代码:

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]
Run Code Online (Sandbox Code Playgroud)

所有类都传递一个param,这是一个自定义比特流类.我的目的是找到一个解决方案,它不需要我在ChildClass中读取ChildClass的idx值.所有子类流读取都应该在子类中完成.

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

这在python中甚至可能吗?有没有办法访问父母的信息?

kin*_*all 11

尽管我有点"赞美"评论(公平竞争称之为!),但实际上有办法实现你想要的东西:不同的继承途径.一对夫妇:

  1. 编写一个装饰器,它在声明类之后对其进行内省,找到内部类,并将外部类中的属性复制到它们中.

  2. 使用元类做同样的事情.

这是装饰器方法,因为它是最直接的:

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
Run Code Online (Sandbox Code Playgroud)

这是一个简单的使用示例:

@matryoshka
class outer(object):

    answer = 42

    class inner(object):

        def __call__(self):
            print self.answer

outer.inner()()   # 42
Run Code Online (Sandbox Code Playgroud)

但是,我不禁想到其他答案中提出的一些想法会更好地为您服务.


iro*_*hon 7

你这里不需要两节课.这是您以更简洁的方式编写的示例代码.

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())]
Run Code Online (Sandbox Code Playgroud)

欢迎使用Python.类在运行时是可变的.请享用.

  • 使用Python而不使用理解就像去坎昆而不去海滩. (7认同)