gpt4 book ai didi

python - 在多个文件和目录中使用Python OOP时,有助于理解分层继承

转载 作者:太空宇宙 更新时间:2023-11-03 20:48:48 25 4
gpt4 key购买 nike

介绍

我是大学学习编程的学生。我的课程侧重于Java,C#和C ++,因此我对OOP有一定的经验。目前,我正忙于合作社,要求是使用Python和tkinter(我正在学习这两者)来创建GUI。

我的问题专门与Python OOP和跨多个目录中的多个文件的继承有关,我根本无法弄清楚(已经3天了)

如果您不想遍历多行缩短的文件和代码示例,则可以在此处找到实际的代码:

https://github.com/bkleynhans/Landsat-Buoy-Calibration.git

然后转到页面底部以获取问题的要点。

除非您安装了ModTran(这是一种昂贵的许可软件),否则您将无法运行校准系统。但是,GUI应该可以完全正常运行,唯一的非标准要求是tkcalendar。

我做了什么

我已经研究了以下链接的线程以及其他成员所包含的链接。

ImportError: cannot import name

ImportError: Cannot import name X

以及

https://www.digitalocean.com/community/tutorials/understanding-class-inheritance-in-python-3

https://www.python-course.eu/python3_inheritance.php

https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-imports.html

不幸的是,无论是因为我不够了解,还是因为我很慢,我似乎都无法将它们与我的问题联系起来。

资料夹结构

我的文件夹结构如下:

Z:.

│ tarca_gui

└───gui

│ __init__.py
│ tarca_gui.py


└───forms

│ input_notebook.py
│ status_frame.py
│ settings_frame.py
│ example_date_picker_supplied.py
│ settings_notebook.py
│ input_frame.py
│ help_menu.py
│ header_frame.py
│ progress_bar.py
│ __init__.py
│ menu_bar.py
│ example_date_picker.py
│ output_frame.py

└─


文件摘要

根目录中的tarca_gui只是一个bash脚本,它会更改为工作目录并执行gui

cd ~/Landsat-Buoy-Calibration/gui
python3 tarca_gui.py


将文件及其代码放在这里会很混乱,但是我将粘贴标题和结构。上面介绍部分中有一个指向该项目的GitHub链接。

必需的非标准库:
tkcalendar- https://pypi.org/project/tkcalendar/

tarca_gui.py-从linux终端启动程序,并使用tkinter构建接口。所有其他文件均基于以下结构派生

基础类

tarca_gui.py

from tkinter import *
from tkinter import messagebox
import inspect
import sys
import os
import pdb

class Tarca_Gui:

def __init__(self, master):

# Import gui paths
from forms import progress_bar
from forms import menu_bar
from forms import header_frame
from forms import input_frame
from forms import output_frame
from forms import status_frame

# Create the root Tkinter object
master.title('CIS Top Of Atmosphere Radiance Calibration System')
master.geometry('800x600')
master.resizable(False, False)
#master.configure(background = '#FFFFFF')

master.option_add('*tearOff', False)

# Create the Progressbar window - accessed via master.progressbar_window.progress_bar
progress_bar.Progress_Bar(master)

# Create the Menubar - accessed via master.menu_bar
menu_bar.Menu_Bar(master)

# Create the Header - accessed via master.header_frame
header_frame.Header_Frame(master)

# Create the Input Frame - accessed via master.
input_frame.Input_Frame(master)

# Create the Input Frame - accessed via master.
output_frame.Output_Frame(master)

# Create the Input Frame - accessed via master.
status_frame.Status_Frame(master)



# Calculate fully qualified path to location of program execution
def get_module_path():

filename = inspect.getfile(inspect.currentframe())
path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))

return path, filename


# Set environment variables to locate current execution path
def set_path_variables():

path, filename = get_module_path()

# find the Calibration program path
path_index = path.rfind('/')

# append gui paths
sys.path.append(path[:path_index])
sys.path.append(path)
sys.path.append(path + "/forms")


def on_closing(root):

if messagebox.askyesno("Quit", "Do you really wish to quit?"):
root.destroy()


def main():

set_path_variables()

root = Tk()
root.protocol("WM_DELETE_WINDOW", lambda: on_closing(root))
tarca_gui = Tarca_Gui(root)
root.mainloop()


if __name__ == "__main__": main()


progress_bar,menu_bar,header_frame,input_frame,output_frame和状态帧均源自(扩展)targa_gui

派生类的摘要

progress_bar.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
import tarca_gui

class Progress_Bar(tarca_gui.Tarca_Gui):
def __init__(self, master):


menu_bar.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
import tarca_gui
import help_menu
from gui.forms import settings_frame

class Menu_Bar(tarca_gui.Tarca_Gui):
def __init__(self, master):


header_frame.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
from forms import input_frame

class Header_Frame(input_frame.Input_Frame):
def __init__(self, master):


input_frame.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
import tarca_gui
from gui.forms import input_notebook

class Input_Frame(tarca_gui.Tarca_Gui):
def __init__(self, master):


output_frame.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
import tarca_gui

class Output_Frame(tarca_gui.Tarca_Gui):
def __init__(self, master):


status_frame.py扩展了tarca_gui.py

from tkinter import *
from tkinter import ttk
import tarca_gui

class Status_Frame(tarca_gui.Tarca_Gui):
def __init__(self, master):


其余类:help_menu,settings_frame,settings_notebook,header_frame和input_notebook源自(扩展)其他类

header_frame.py扩展了input_frame.py

from tkinter import *
from tkinter import ttk
from forms import input_frame.py
import pdb
class Header_Frame(input_frame.Input_Frame):
def __init__(self, master):


input_notebook.py扩展了input_frame.py

from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from gui.forms import input_frame
from tkcalendar import Calendar, DateEntry
from datetime import date

class Input_Notebook(input_frame.Input_Frame):
def __init__(self, master):


help_menu.py扩展了menu_bar.py

from tkinter import *
from tkinter import ttk
import time
import threading
import menu_bar

class Help_Menu(menu_bar.Menu_Bar):
def __init__(self, master):


settings_frame.py扩展了settings_notebook.py

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from gui.forms import menu_bar
from gui.forms import settings_notebook

class Settings_Frame(menu_bar.Menu_Bar):
def __init__(self, master):


settings_notebook.py扩展了settings_frame.py

from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from gui.forms import settings_frame

class Settings_Notebook(settings_frame.Settings_Frame):
def __init__(self, master):


问题与疑问

首先,通过您可以在基类中查看的功能启动gui时,会更新PYTHONPATH。

其次,我了解到,目前这些类并不是全部以相同的方式导入,在寻找问题的过程中它们已经并且已经更改,并且在解决问题后将对其进行标准化。

问题

在尝试将Settings_Frame导入settings_notebook.py之前,整个GUI都可以正常工作

收到错误

% ./tarca_gui
Traceback (most recent call last):
File "tarca_gui.py", line 104, in <module>
if __name__ == "__main__": main()
File "tarca_gui.py", line 100, in main
tarca_gui = Tarca_Gui(root)
File "tarca_gui.py", line 31, in __init__
from forms import menu_bar
File "/cis/otherstu/bxk8027/Landsat-Buoy-Calibration/gui/forms/menu_bar.py", line 20, in <module>
import help_menu
File "/cis/otherstu/bxk8027/Landsat-Buoy-Calibration/gui/forms/help_menu.py", line 21, in <module>
import menu_bar
File "/cis/otherstu/bxk8027/Landsat-Buoy-Calibration/gui/forms/menu_bar.py", line 21, in <module>
from gui.forms import settings_frame
File "/cis/otherstu/bxk8027/Landsat-Buoy-Calibration/gui/forms/settings_frame.py", line 21, in <module>
from gui.forms import settings_notebook
File "/cis/otherstu/bxk8027/Landsat-Buoy-Calibration/gui/forms/settings_notebook.py", line 25, in <module>
class Settings_Notebook(settings_frame.Settings_Frame):
AttributeError: module 'gui.forms.settings_frame' has no attribute 'Settings_Frame'


发现

我相信这是由于循环导入引起的,因为settings_frame导入settings_notebook,反之亦然。

混乱

我了解应尽可能避免使用循环引用,但是,按照我目前了解Python OOP的方式,我需要将settings_notebook导入settings_frame以进行构造,但同时我也需要将settings_frame导入settings_notebook以便对其进行扩展(settings_notebook应该是settings_frame的子级)

问题

我不知道我在做什么错。


它与导入相关,还是我构建类的方式?
如果我对类结构(带有导入项)的理解不正确,请解释我做错了什么,以便我可以学习而不会再犯同样的错误。
任何其他有关的建议将不胜感激。


结论

如果您已经做到了这一点,首先,非常感谢。

如前所述,我在大学里同时学习C ++,C#,Java,Python,HTML,CSS,JavaScript,PHP,SQL,Unity和Unreal引擎(有时我对它们之间的概念感到困惑),因此有关的任何建议我的代码的任何部分将不胜感激。

最佳答案

这段代码确实很难解开,但是我认为问题的根源在于您试图使用继承在类之间共享数据。那不是继承的目的。

当B从A继承时,并不意味着B共享A的数据,这意味着B是A的精确副本,但具有一些增强功能。实际上,您有两个A-原始A和一个具有某些其他功能的新A。

例如,您有一个名为Tarca_Gui的类。这似乎是主要课程。它具有状态栏,菜单栏等。当您从Tarca_Gui继承时,该新类还具有状态栏,菜单栏等。这两个类不共享任何数据。

代替继承,您需要使用组合。区别在于,继承Menu_BarTarca_Gui,但是您真正想要的是Tarca_Gui具有Menu_Bar

因为您没有提供minimal reproducible example,所以我无法修复您的代码,但是您需要做的第一件事是从每个类的定义中删除Tarca_Gui。然后,将Tarca_Gui的实例传递给其他各种对象。

换一种说法:

class Tarca_Gui():
def __init__(self, master):
...
self.menu_bar = Menu_Bar(self)
self.header_frame.Header_Frame(self)
self.input_frame = Input_Frame(self)
self.output_frame = Output_Frame(self)
self.status_frame = Status_Frame(self)
...

class Menu_Bar():
def __init__(self, tarca_gui):
self.tarca_gui = tarca_gui
...
class Progress_Bar():
def __init__(self, tarca_gui):
self.tarca_gui = tarca_gui
...
class Header_Frame():
def __init__(self, tarca_gui):
self.tarca_gui = tarca_gui
...
... and so on ...


然后,在每个这些对象中,如果它们需要由 Tarca_Gui管理的内容,则可以使用 self.tarca_gui进行引用。例如,如果您需要访问 master小部件,则可以使用 self.tarca_gui.master

同样, Menu_BarInput_FrameSettings_Frame都不应继承任何内容。

有关继承与组合的更多信息,请参见 Difference between Inheritance and Composition

关于python - 在多个文件和目录中使用Python OOP时,有助于理解分层继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56400317/

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