Python v2嵌套子类“全局名称”“未定义”
首先,让我说,是的,我已经广泛研究了这几天,现在没有运气。我看过很多例子和类似的情况,例如,但到目前为止,还没有什么能够解决我的问题 我的问题是我有一个Python项目,它有一个主类,有两个嵌套类是的,我知道,其中一个类是第一个类的子类。我不明白为什么我总是得到NameError:全局名称“InnerSubClass”没有定义 我知道范围界定问题中的两个类都在同一个范围内,但我尝试的任何方法似乎都无法解决我希望将这两个类嵌套在最低限度内的问题,尽管这个问题适用于其他人 下面是一个简单的例子,说明我正在尝试做什么:Python v2嵌套子类“全局名称”“未定义”,python,class,python-2.x,Python,Class,Python 2.x,首先,让我说,是的,我已经广泛研究了这几天,现在没有运气。我看过很多例子和类似的情况,例如,但到目前为止,还没有什么能够解决我的问题 我的问题是我有一个Python项目,它有一个主类,有两个嵌套类是的,我知道,其中一个类是第一个类的子类。我不明白为什么我总是得到NameError:全局名称“InnerSubClass”没有定义 我知道范围界定问题中的两个类都在同一个范围内,但我尝试的任何方法似乎都无法解决我希望将这两个类嵌套在最低限度内的问题,尽管这个问题适用于其他人 下面是一个简单的例子,说明
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()
我已经试过改变SupernnerSubclass了
到
SupernnerClass.InnerSubClass.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
甚至
superMainClass.InnerClass.InnerSubClass.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我让InnerSubClass直接从对象InnerSubassObject:etc继承,但它仍然不起作用
诚然,我远非一个经验丰富的python开发人员,而且大多来自其他编译过的OO语言,我似乎无法理解为什么这不起作用。如果我去掉InnerSubClass,一切都会正常工作
python似乎不像其他语言那样提供私有类和函数,这很好,但我想利用嵌套至少将对象集中在一起。在这种情况下,除了MainClass中的函数外,不应该实例化InnerClass或InnerSubClass
请提供有用的建议,并解释为什么它不能像预期的那样工作,以及如何正确完成这项工作的背景信息。如果这是看起来那么简单的话,那么现在就已经解决了
编辑:为了澄清,这只适用于v2,他们是这样做的
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
他们是这样做的
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
查找顺序中没有类作用域
创建新类时,将执行主体中的代码,并将生成的名称传递给type进行创建。Python查找从内部到外部进行,但没有类级别,只有定义为新类的属性/方法的名称。事实上,如果要访问方法内部的类变量,可以使用MyClass.attr而不是简单的attr
继承之所以有效,是因为InnerSubassinerClass发生在类创建内部。要在创建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是全局定义的。如果将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
查找顺序中没有类作用域
创建新类时,将执行主体中的代码,并将生成的名称传递给type进行创建。Python查找从内部到外部进行,但没有类级别,只有定义为新类的属性/方法的名称。事实上,如果要访问方法内部的类变量,可以使用MyClass.attr而不是简单的attr
继承之所以有效,是因为InnerSubassinerClass发生在类创建内部。要在创建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是全局定义的。如果将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
如果您有不使用MainClass.InnerSubClass的原因,您也可以使用typeself或self.\u uu class\u uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。这在很多层次上都能很好地工作,但无论如何都不应该发生,并且要求传递给super的参数是实例的类型,无论如何它都应该是实例的类型,但如果您使用子类,则会中断,如图所示。这个概念可能比范围界定规则更清晰:
class MainClass:
class Inner:
pass
class InnerSub(Inner):
def __init__(self):
print(super(self.__class__))
print(super(type(self)))
MainClass().InnerSub()
如果您有不使用MainClass.InnerSubClass的原因,您也可以使用typeself或self.\u uu class\u uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。这很有效 很多层很深,无论如何都不应该发生,并且要求传递给super的参数是实例的类型,无论如何它都应该是实例的类型,但如果您创建子类,则会中断,如图所示。这个概念可能比范围界定规则更清晰:
class MainClass:
class Inner:
pass
class InnerSub(Inner):
def __init__(self):
print(super(self.__class__))
print(super(type(self)))
MainClass().InnerSub()
正如你在我的原始帖子中所看到的,我已经尝试过了,还有其他几个版本正在寻找解决方案。谢谢你的建议。抱歉,但我认为你没有使用它,至少你没有提到它MainClass.InnerSubClass,它在没有error@DoS:这不是您在帖子中说您尝试过的变体之一,您可能还没有尝试过,因为它是正确的变体。很抱歉,您的评论太晚了。我确实尝试过这个,我得到了TypeError:超级参数1必须是type,而不是str。在mac上使用相同的代码,我得到了TypeError:必须是type,而不是strstr@DoS:该错误是因为您做了一些未向我们展示的错误,很可能是重复使用了名称或键入错误。我们说不出来,因为你还没有给我们看。正如你在我的原始帖子中看到的,我已经尝试过了,还有其他几个版本正在寻找解决方案。谢谢你的建议。抱歉,但我认为你没有使用它,至少你没有提到它MainClass.InnerSubClass,它在没有error@DoS:这不是您在帖子中说您尝试过的变体之一,您可能还没有尝试过,因为它是正确的变体。很抱歉,您的评论太晚了。我确实尝试过这个,我得到了TypeError:超级参数1必须是type,而不是str。在mac上使用相同的代码,我得到了TypeError:必须是type,而不是strstr@DoS:该错误是因为您做了一些未向我们展示的错误,很可能是重复使用了名称或键入错误。我们说不出来,因为你还没有告诉我们。我想我明白你的意思,但你说的是嵌套而不是继承。我对嵌套类没有问题,它的子类化导致了这个问题。使用您的示例,应该能够instasiate Inner并将其从Outer继承,值为1。除非排除不起作用的示例,否则您的问题是嵌套。我将添加一个与您的类相匹配的示例。@DoS请确保对这个答案也投反对票,因为海报没有显式地传递带有类声明的对象,因此它在Python 2.x上不起作用。类作用域是一个作用域。这不是一个有效的闭包作用域,但它是一个作用域。@user2357112 arghh,完全正确,对不起。我希望编辑能让它足够清晰,否则请随意突出显示更好。我想我明白你的意思,但你说的是嵌套而不是继承。我对嵌套类没有问题,它的子类化导致了这个问题。使用您的示例,应该能够instasiate Inner并将其从Outer继承,值为1。除非排除不起作用的示例,否则您的问题是嵌套。我将添加一个与您的类相匹配的示例。@DoS请确保对这个答案也投反对票,因为海报没有显式地传递带有类声明的对象,因此它在Python 2.x上不起作用。类作用域是一个作用域。这不是一个有效的闭包作用域,但它是一个作用域。@user2357112 arghh,完全正确,对不起。我希望编辑能让它足够清晰,否则请随意突出显示。这是人们常犯的错误。super的第一个参数必须是定义该方法的类,而不是typeself或self。typeself和self.\uuuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。用这种方式使用super是一个非常危险的举动,它会向那些可能没有意识到危险的人传播危险的行为。这是人们常犯的错误。super的第一个参数必须是定义该方法的类,而不是typeself或self。typeself和self.\uuuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。以这种方式使用super是一个非常危险的举动,它会将危险的做法传播给那些可能没有意识到危险的人。