关于class:python v2嵌套子类”global name’<class name>’未定义”

Python v2 nested subclass “global name '<ClassName>' is not defined”

首先,让我说,是的,我已经广泛研究了这几天,现在没有运气。我看过很多例子和类似的情况,比如这一个,但是到目前为止还没有什么能解决我的问题。

我的问题是我有一个Python项目,它有一个主类,有两个嵌套类(是的,我知道),其中一个类是第一个类的子类。我弄不明白为什么我要一直得到NameError: global name 'InnerSubClass' is not defined

我了解范围界定(两个讨论中的类都在同一范围内),但我尝试的任何操作似乎都无法解决问题(我希望将两个类至少嵌套在一起),尽管这个问题对其他人有效。

下面是一个简单的例子,说明我要做的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class SomeClass(object):
        def __init__(self):

           """lots of other working stuff"""


class MainClass(object):
    def __init__(self):
        self.stuff = []
        self.moreStuffs = []

    class InnerClass(object):
        def __init__(self, thing, otherThing):
            self.thing = thing
            self.otherThing = otherThing
            self.otherStuff = []

    class InnerSubClass(InnerClass):
        def __init__(self, thing, otherThing, newThing):
            super(InnerSubClass).__init__(thing, otherThing)
            self.newThing = newThing

       """other code that worked before the addition of 'InnerSubClass'"""

    def doSomething(self):
        innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
        print("just more thing words %s" % innerclass.newThing)


myThing = MainClass()
myThing.doSomething()

我已经试着换过了。到super(InnerClass.InnerSubClass).__init__(thing, otherThing)甚至没有成功。我让"innersubclass"直接从对象InnerSubClass(object):等继承,但它仍然不起作用。

当然,我远不是一个经验丰富的Python开发人员,而且大部分来自其他编译的OO语言,而且似乎无法理解为什么这不起作用。如果我去掉了"内部子类",一切都会正常工作。

似乎Python不像其他语言那样提供"私有"类和函数,这很好,但我希望利用嵌套至少将对象"集中"在一起。在这种情况下,除了"mainClass"中的函数外,不应该实例化"innerClass"或"innerSubClass"。

请提供有用的建议,并解释为什么它不能按预期工作,以及应该如何正确完成的背景信息。如果这看起来这么简单的话,现在就可以解决了。

编辑:为了澄清,这只适用于V2


查找顺序中没有"类范围"

创建新类时,将执行主体中的代码,并将生成的名称传递给type以进行创建。python查找从内部到外部进行,但您没有"类级别",只有定义为成为新类的属性/方法的名称。实际上,如果要访问方法内的类变量,可以使用MyClass.attr,而不是简单的attr

继承工作是因为InnerSubClass(InnerClass)发生在类创建中。要在创建MainClass之后访问InnerClass,请执行与类属性相同的操作:MainClass.InnerClass

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Outer:
    out = 1
    class Inner:
        inside = 2
        try:
            print(out)  # this is confusing
        except NameError:
            print("can't find out")
        def f(self):
            try:
                print(inside)  # this is clear
            except NameError:
                print("can't find inside")
        try:
            print(Inner.inside)  # this is less clear
        except NameError:
            print("can't find Inner.inside")
Outer.Inner().f()
# can't find anything

编辑:

上面是一个通用视图,要将其直接应用于您的情况,请按照查看常规类属性的方式查看内部类。您可以使用MyClass.attr,其中MyClass是全局定义的。如果用InnerSubClass替换attr,则会得到类(属性查找不关心继承,而是关心属性在哪里)。

带有嵌套继承类的简化示例:

1
2
3
4
5
6
7
8
9
class MainClass(object):
    class Inner(object):
        pass
    class InnerSub(Inner):
        def __init__(self):
            print(super(MainClass.InnerSub))  # note you use MainClass, known globally
    def f(self):
        return self.InnerSub()
MainClass().f()  # prints"<super ...>" and returns a MainCLass.InnerSub object


他们这样做的

1
super(MainClass.InnerSubClass, self).__init__(thing, otherThing)

为了测试它,这里是完整的工作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class SomeClass(object):
        def __init__(self):

           """lots of other working stuff"""


class MainClass(object):
    def __init__(self):
        self.stuff = []
        self.moreStuffs = []

    class InnerClass(object):
        def __init__(self, thing, otherThing):
            self.thing = thing
            self.otherThing = otherThing
            self.otherStuff = []

    class InnerSubClass(InnerClass):
        def __init__(self, thing, otherThing, newThing):
            super(MainClass.InnerSubClass, self).__init__(thing, otherThing)
            self.newThing = newThing

       """other code that worked before the addition of 'InnerSubClass'"""

    def doSomething(self):
        innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
        print("just more thing words %s" % innerclass.newThing)

        print("and I also inherit from InnerClass %s" % innerclass.otherThing)


myThing = MainClass()
myThing.doSomething()

输出是

1
2
just more thing words thingthing
and I also inherit from InnerClass thatthing


如果你有理由不使用MainClass.InnerSubClass,你也可以使用type(self)self.__class__(好的,但是哪个)在__init__里面得到包含类。这可以很好地工作很多层深度(无论如何都不应该发生),并且要求传递给super的参数是实例的类型(无论如何应该是这种类型),但如果您是子类,则会中断,如图所示。这个概念对你来说可能比范围规则更清楚:

1
2
3
4
5
6
7
8
class MainClass:
    class Inner:
        pass
    class InnerSub(Inner):
        def __init__(self):
            print(super(self.__class__))
            print(super(type(self)))
MainClass().InnerSub()