Python v2嵌套子类“global name”<ClassName>“未定义”

2024-03-29 09:54:24 发布

您现在位置:Python中文网/ 问答频道 /正文

首先,让我说,是的,我已经广泛地研究了这几天,现在没有运气。我已经看过很多例子和类似的情况,比如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”或“innersublass”。你知道吗

请提供有用的建议,并解释为什么它不能像预期的那样工作,以及如何正确地完成这项工作的背景信息。如果这像看上去那么简单的话,现在就已经解决了。你知道吗

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


Tags: selfobjectinitdef情况作用域class例子
3条回答

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

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

继承之所以有效,是因为InnerSubClass(InnerClass)发生在类创建内部。要在创建MainClass之后访问InnerClass,请执行与类属性相同的操作: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是全局定义的。如果用InnerSubClass替换attr,则得到类(属性查找不关心继承,而是关心属性的位置)。你知道吗

嵌套继承类的精简示例:

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

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

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

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

相关问题 更多 >