Python v2嵌套子类“未定义全局名称'<classname>'”

时间:2019-02-16 11:06:14

标签: python class python-2.x

首先,我要说的是,我已经对这方面进行了广泛的研究,但是没有运气。我查看了许多示例和类似情况,例如this one,但到目前为止,没有任何事情能够解决我的问题。

我的问题是我有一个Python项目,该项目有一个主类,有两个嵌套类(是的,我知道),其中一个类是第一个的子类。我无法弄清楚为什么我不断得到NameError: global name 'InnerSubClass' is not defined

我了解范围界定(两个有问题的类都在同一范围内),但是尽管这个问题对其他人也有效,但我没有尝试解决任何问题(我想将两个类的嵌套数量降到最低)。

这是我要执行的操作的一个简单示例:

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(InnerSubClass).__init__(thing, otherThing)super(InnerClass.InnerSubClass).__init__(thing, otherThing) 乃至 super(MainClass.InnerClass.InnerSubClass).__init__(thing, otherThing)没有成功。我使“ InnerSubClass”直接从对象InnerSubClass(object):等继承,但仍然无法正常工作。

当然,我不是一个经验丰富的python开发人员,而且来自大多数其他编译的OO语言,而且似乎无法解决为什么它不起作用的问题。如果我摆脱了“ InnerSubClass”,一切都会很好。

似乎python并不像其他语言一样提供“私有”类和函数,这很好,但是我想利用嵌套至少将“聚集”的对象保持在一起。在这种情况下,除了“ MainClass”中的函数外,什么都不应实例化“ InnerClass”或“ InnerSubClass”。

请提供有用的建议,并通过有关如何正确完成操作的背景信息,说明为什么它无法按预期工作。如果这看起来很简单,那么现在应该已经知道了。

编辑:为澄清起见,仅适用于v2

3 个答案:

答案 0 :(得分:4)

按查找顺序没有“类范围”

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

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

仅举一个例子:

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是全局定义的。如果将attr替换为InnerSubClass,则会得到该类(属性查询与继承无关,而与属性的位置有关)。

一个带有嵌套继承类的精简示例:

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 :(得分:1)

Here他们是这样做的

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

因此您可以在这里进行测试,这是完整的工作示例

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

输出为

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

答案 2 :(得分:0)

如果您有理由不使用MainClass.InnerSubClass,则还可以在type(self)内使用self.__class____init__OK, but which one)来获取包含的类。这可以在很多层上很好地工作(无论如何都不应该发生),并且要求传递给super的参数是实例的类型(无论如何应该是),但是如果您子类化< / strong>,如here所示。比起范围规则,这个概念对您而言可能更清晰:

class MainClass:
    class Inner:
        pass
    class InnerSub(Inner):
        def __init__(self):
            print(super(self.__class__))
            print(super(type(self)))
MainClass().InnerSub()