gpt4 book ai didi

python - 在 Jython 中使用 getattr 时出现 StackOverflowError

转载 作者:行者123 更新时间:2023-12-01 04:27:44 24 4
gpt4 key购买 nike

我正在用 Jython 编写一个文本编辑器。该文本编辑器有一个工具栏,它通过 ToolbarView 类显示并由 ToolbarController 类处理。有些操作无法由 ToolbarController 单独处理,因此这些操作被委托(delegate)给 MainController 类。

为了避免重复代码,因为有许多操作从 ToolbarController 委托(delegate)给 MainController,我按照我问的上一个问题 here 中的建议使用了 getattr。 。我还意识到我可以在 ToolbarView 代码中使用相同的机制来执行按钮的操作,但我无法让它工作,最终会出现无限循环和 Java StackOverflowError.

这是相关代码的摘录:

ToolbarView类:

from javax.swing import JToolBar, ImageIcon, JButton

class ToolbarView(JToolBar):

def __init__(self, controller):

#Give reference to controller to delegate action response
self.controller = controller

options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']
for option in options:
methods[option] = "on" + option + "Click"
print methods[option]

for name, method in methods.items():
button = JButton(name, actionPerformed=getattr(self, method))
self.add(button)

def __getattr__(self, name):
return getattr(self.controller, name)

ToolbarController类:

from .ToolbarView import ToolbarView
class ToolbarController(object):

def __init__(self, mainController):

#Create view with a reference to its controller to handle events
self.view = ToolbarView(self)

#Will also need delegating to parent presenter
self.mainController = mainController

def __getattr__(self, name):
return getattr(self.mainController, name)

MainController 类:

from .ToolbarController import ToolbarController

class MainController(object):

def __init__(self):
self.toolbarController = ToolbarController(self)

def onNewFileClick(self, event):
print("MainController: Creating new file...")

def onEditFileClick(self, event):
print("MainController: Editting new file...")

def onSaveFileClick(self, event):
print("MainController: Saving new file...")

def onCloseFileClick(self, event):
print("MainController: Closing new file...")

所以我期望的是,当我单击按钮时,MainController.onNewFileClick 将被执行并在控制台中打印出该消息。如果我想从 ToolbarView 委托(delegate)给 ToolbarController,它就可以工作,但是当我将该委托(delegate)从 ToolbarController 传递给 ToolbarController 时,它就不起作用了。主 Controller 。它似乎在无限循环中调用自己。我得到的错误是:

Traceback (most recent call last):
File "main.py", line 3, in <module>
MainController()
File "/home/training/Jython/controller/MainController", line 8, in __init__
self.toolbarController = ToolbarController(self)
File "/home/Jython/controller/ToolbarController.py", line 8, in __init__
self.view = ToolbarView(self)
File "/home/Jython/controller/ToolbarView.py", line 44, in __init__
button = JButton(name, actionPerformed=getattr(self, method))
File "/home/Jython/controller/ToolbarView.py", line 54, in __getattr__
return getattr(self.controller, name)
File "/home/Jython/controller/ToolbarController.py", line 15, in __getattr__
return getattr(self.mainController, name)
File "/home/Jython/controller/ToolbarController.py", line 15, in __getattr__
return getattr(self.mainController, name)

[...]

File "/home/Jython/controller/ToolbarController.py", line 15, in __getattr__
return getattr(self.mainController, name)
RuntimeError: maximum recursion depth exceeded (Java StackOverflowError)

我做错了什么?我在 python 中尝试过类似的方法(从一个类委托(delegate)给另一个类到另一个类),如果在 getattr 之后放置 () ,它就可以工作,但在这里我因为 而感到困惑JButton 中的actionPerformed。我已经尝试过了,但结果是一样的。

最佳答案

看来您正在使用Jython,我真的不知道。无论如何,在 python 中,您重写了 __getattr__,那么您应该期望 getattr 使用您重写的钩子(Hook)。所以我认为你真正的意思是:

class ToolbarView(JToolBar):

def __init__(self, controller):

#Give reference to controller to delegate action response
self.controller = controller

options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']
for option in options:
methods[option] = "on" + option + "Click"
print methods[option]

for name, method in methods.items():
button = JButton(name, actionPerformed=super(ToolbarView, self).__getattr__(method))
self.add(button)

def __getattr__(self, name):
return getattr(self.controller, name)

观察按钮是如何创建的。

就为什么你遇到这样的问题而言,这是因为 getattr 的处理方式。如果您覆盖__getattr__,则仅当您尝试引用未定义的字段时才会调用此 Hook :

>>> class A(object):
defined = True
def __getattr__(self, name):
print "referenced :" + name


>>> a = A()
>>> a.defined
True
>>> a.undefined
referenced :undefined

希望现在清楚这个钩子(Hook)是如何工作的。

所以SO实际上是由于您引用了不属于MainController的东西引起的。

在您的 MainController 中,仅定义了 onNewFileClick,但您定义了其他 3 个选项:

options= ['NewFile', 'OpenFile', 'SaveFile', 'CloseFile']

所以,这将在第二轮迭代时发生。由于 MainController 没有 onOpenFileClick,因此会引发 AttributeError,但会被 ToolbarController 捕获,因此会覆盖 code>__getattr__ 被不断地调用。这就是你的调用堆栈爆炸的原因。

关于python - 在 Jython 中使用 getattr 时出现 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32869430/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com