Python v2嵌套子类“全局名称” ' 没有定义”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python v2嵌套子类“全局名称” ' 没有定义”相关的知识,希望对你有一定的参考价值。

首先,让我说是的,我已经研究了几天,现在没有运气。我看过很多例子和类似的情况,比如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

答案

There is no "class scope" in lookup order

创建新类时,将执行正文中的代码,并将生成的名称传递给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
另一答案

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
另一答案

如果你有理由不使用MainClass.InnerSubClass,你也可以在type(self)中使用self.__class__OK, but which one__init__)来获得包含类。这很好地适用于很多层(无论如何都不应该发生),并且要求传递给super的参数是实例的类型(它应该是它应该是)但是如果你是子类,则会中断,如here所示。这个概念可能比范围规则更清晰:

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

以上是关于Python v2嵌套子类“全局名称” ' 没有定义”的主要内容,如果未能解决你的问题,请参考以下文章

Python/函数的嵌套和闭包

python基础之名称空间和作用域函数嵌套

Python-函数基础

013.Python之函数嵌套名称空间与作用域闭包函数

11.11函数对象,名称空间,作用域,命名关键字参数

python-之名称空间与作用域闭包函数嵌套函数