Python 如何调用包含不同类中函数的函数?

Python 如何调用包含不同类中函数的函数?,python,class,tkinter,methods,Python,Class,Tkinter,Methods,我在Python3中使用Tkinter,有两个窗口,每个窗口由一个类表示。我需要单击WindowB(我的第二个类)中运行WindowA(我的第一个类)方法的按钮。这应该没问题,但是我调用的方法从WindowA(我的第一个类)调用另一个方法。这导致错误:AttributeError:“WindowB”对象没有属性“functionB”。 如何修复此问题,以便在WindowB(第二类)中运行Function时不会出现错误? 代码: 要使用WindowA函数,必须从WindowA类创建实例 class

我在Python3中使用Tkinter,有两个窗口,每个窗口由一个类表示。我需要单击WindowB(我的第二个类)中运行WindowA(我的第一个类)方法的按钮。这应该没问题,但是我调用的方法从WindowA(我的第一个类)调用另一个方法。这导致错误:AttributeError:“WindowB”对象没有属性“functionB”。 如何修复此问题,以便在WindowB(第二类)中运行Function时不会出现错误? 代码:


要使用WindowA函数,必须从WindowA类创建实例

class WindowB(Toplevel):
    def __init__(self, master=None):
        Toplevel.__init__(self, master)
        self.master = master
        self.Window()
        self.WindowA = WindowA()  # added here

    def Window(self):
        button3 = Button(self, text='Run Function A', command=lambda: self.WindowA.functionA())
        button3.grid(row=1, column=0, padx=10)

作为替代答案,您可以使用
classmethod
decorator:

    def functionA(self):
        print("I am function A.")
        WindowA.functionB()

    @classmethod
    def functionB(cls):
        print("I am function B, called from function A.")

注意,我正在调用
WindowA.functionB()
您就快到了,您只需要在类
WindowB
的tge
Window()
方法中更改一件事。您需要将其更改为这样:

button3 = Button(self, text = 'Run Function A', command = lambda:WindowA().functionA())
# instead of 
# button3 = Button(self, text = 'Run Function A', command = lambda:WindowA.functionA(self))

最常见的解决方案是在创建
WindowB
时传递
WindowA
的实例,以便后者可以访问前者中的方法

首先,确保
WindowB
可以接受另一个窗口的名称:

class WindowB(Toplevel):
    def __init__(self, master = None, windowA=None):
        Toplevel.__init__(self, master)
        self.master = master
        self.windowA=windowA
        self.Window()
接下来,在创建
WindowB
实例时,将
self
作为
windowA
参数传递。我将
object
重命名为
self
,因为您传递的是一个类而不是该类的实例:

class WindowA(Frame):
    ...
    def changeWindow(self, cls):
        root.withdraw()
        currentFrame = cls(root, windowA=self)
然后可以使用
self.windowA
调用该对象中的任何方法:

class WindowB(Toplevel):
    ...
    def Window(self):
        ...
        button3 = Button(self, text = 'Run Function A', command = lambda:self.windowA.functionA())
        ...

这回答了你的问题吗?非常感谢。我在我的实际程序中尝试了这些方法,但没有成功。这可能是因为我调用方法的“WindowA”是一个“顶级”而不是一个框架吗?它对我来说很好。。。尝试将代码从我的答案复制到您的应用程序当我在项目中实现此功能时,从中调用方法的类的窗口(在本例中为WindowA)打开,导致错误:“NoneType对象没有属性”“title”“。我只是在实际代码中实现了此功能,但它似乎不起作用,抱歉。它会打开两个空白窗口(调用该方法的类的窗口和当前类的窗口)。@StudyAccount我用您的代码对其进行了测试,但它仍在工作,可能您稍后更改了什么?您是正确的:')。在我的程序中,我需要编写self.WindowA=WindowA(root)的等价物。这将完全打开WindowA和WindowB,但我可以编写self.WindowA.draw()来只显示WindowB并运行我的方法。谢谢已有一个
WindowA
的实例。此解决方案创建了第二个实例。我想我理解这一点,但只是想检查一下,当我调用changeWindow方法时,您是否建议在创建WindowB时,self的参数是WindowB,而object的参数是self?(如果这是一个愚蠢的问题,我很抱歉)@StudyAccount:我很抱歉。我在创建示例方面做得很差。您的代码对命名方式和不遵循PEP8命名约定的事实非常混乱。我想我现在明白了。关键是,为了让B能够调用A中的某个内容,B需要有A的引用。谢谢!我会先对装饰师做一些研究,我会尝试在未来的项目中使用它。这是个好主意。
classmethod
decorator基本上只允许调用类方法,就像调用普通模块函数一样。它非常适合您的示例,因为该函数实际上没有使用
self
。然而,我应该指出,classmethod的第一个参数通常不是
self
。它通常是类对象
cls
。文件在这里
class WindowB(Toplevel):
    ...
    def Window(self):
        ...
        button3 = Button(self, text = 'Run Function A', command = lambda:self.windowA.functionA())
        ...