Python重写类时触发NameError:InterfaceWithNoMenu未定义
Kivy Settings模块嵌套类引用错误问题解决
我基于Kivy框架开发Python GUI应用,尝试修改Settings模块的外观、样式与行为。编写了嵌套类结构的代码,但创建Settings窗口实例时,SettingsWithNoMenu类的__init__方法中引用InterfaceWithNoMenu时触发错误:
self.interface_cls = InterfaceWithNoMenu NameError: name 'InterfaceWithNoMenu' is not defined
InterfaceWithNoMenu类就在SettingsWithNoMenu类的下方定义,却找不到它,特此求助。
代码示例
class Settings(Screen): class SettingsWithNoMenu(kivy.uix.settings.SettingsWithNoMenu): def __init__(self, *args, **kwargs): self.interface_cls = InterfaceWithNoMenu kivy.uix.settings.SettingsWithNoMenu.__init__( self, *args, **kwargs ) class InterfaceWithNoMenu(kivy.uix.settings.ContentPanel): def add_widget(self, widget): if self.container is not None and len(self.container.children) > 0: raise Exception( 'ContentNoMenu cannot accept more than one settings panel') super(InterfaceWithNoMenu, self).add_widget(widget) kivy.uix.settings.InterfaceWithNoMenu.__init__( self, *args, **kwargs ) actionview = ObjectProperty(None) settings_content = ObjectProperty(None) def __init__(self, **kwargs): super(Settings, self).__init__(**kwargs) ...
问题原因
Python解析类定义是按从上到下的顺序执行的。当SettingsWithNoMenu的__init__方法引用InterfaceWithNoMenu时,这个类还未被定义(它在SettingsWithNoMenu之后才声明),因此触发NameError。另外,嵌套类的作用域属于外层类,直接跨顺序引用会超出当前解析范围。
解决方法
方法1:调整嵌套类定义顺序
把InterfaceWithNoMenu移到SettingsWithNoMenu之前定义,确保解析到SettingsWithNoMenu时,目标类已经存在:
class Settings(Screen): class InterfaceWithNoMenu(kivy.uix.settings.ContentPanel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def add_widget(self, widget): if self.container is not None and len(self.container.children) > 0: raise Exception('ContentNoMenu cannot accept more than one settings panel') super().add_widget(widget) class SettingsWithNoMenu(kivy.uix.settings.SettingsWithNoMenu): def __init__(self, *args, **kwargs): self.interface_cls = InterfaceWithNoMenu kivy.uix.settings.SettingsWithNoMenu.__init__( self, *args, **kwargs ) actionview = ObjectProperty(None) settings_content = ObjectProperty(None) def __init__(self, **kwargs): super(Settings, self).__init__(**kwargs) ...
方法2:通过外层类引用内部类
如果不想调整顺序,可以通过外层Settings类来指定InterfaceWithNoMenu,利用外层类的属性访问内部嵌套类:
class Settings(Screen): class SettingsWithNoMenu(kivy.uix.settings.SettingsWithNoMenu): def __init__(self, *args, **kwargs): # 通过外层类定位内部类 self.interface_cls = Settings.InterfaceWithNoMenu kivy.uix.settings.SettingsWithNoMenu.__init__( self, *args, **kwargs ) class InterfaceWithNoMenu(kivy.uix.settings.ContentPanel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def add_widget(self, widget): if self.container is not None and len(self.container.children) > 0: raise Exception('ContentNoMenu cannot accept more than one settings panel') super().add_widget(widget) actionview = ObjectProperty(None) settings_content = ObjectProperty(None) def __init__(self, **kwargs): super(Settings, self).__init__(**kwargs) ...
额外修正说明
原代码中InterfaceWithNoMenu类存在两个问题:
add_widget方法中调用了kivy.uix.settings.InterfaceWithNoMenu.__init__,但你的类继承的是ContentPanel,且方法未声明*args, **kwargs参数,会导致参数错误,建议移除该调用或修正继承关系。- 调用父类方法时可以使用简化的
super()语法,无需显式指定类名和self参数。
内容的提问来源于stack exchange,提问作者Michael Altfield
相关产品推荐
相关产品推荐

