Я не могу получить доступ к переменным из одного класса в другом - Python

Я изучаю ООП и делаю калькулятор. У меня есть классы для основной программы (родительской программы), кнопок и записей.

Основная программа:

class Program(tk.Tk): 

    def __init__(self, title, size): 
        super().__init__()
        self.title(title)
        self.geometry(f"{size[0]}x{size[1]}")

        # Program elements split into widget type
        self.entries = Entries(self) 
        self.output = Output(self)
        self.buttons = Buttons(self)

Записи:

class Entries(ttk.Frame):
    
    def __init__(self, parent): 
        super().__init__(parent) 
        self.place(x = 0, y = 0) 

        # Calling widget generator and placer functions
        self.entryGen() 
        self.entryPlacer()
    
    def entryGen(self): # Create entry widgets
        self.firstTerm = ttk.Entry(self) 
        self.commonDifference = ttk.Entry(self)
        self.numberOfTerms = ttk.Entry(self)
    
    def entryPlacer(self): # Place entry widgets
        self.firstTerm.pack()
        self.commonDifference.pack()
        self.numberOfTerms.pack()

Кнопки:

class Buttons(ttk.Frame):

    def __init__(self, parent):
        super().__init__(parent)
        self.place(x = 0, y = 0)

        self.buttonGen()
        self.buttonPlacer()

    def buttonGen(self):
        self.clear = ttk.Button(self, text = "Clear", command = lambda: self.clear)
        self.calculate = ttk.Button(self, text = "Calculate", command = lambda: self.calculate)
    
    def buttonPlacer(self):
        self.clear.pack()
        self.calculate.pack()
    
    def clear(self):
        pass

    def calculate(self):
        entries = Entries()
        try:
            print(entries.firstTerm.get() + entries.commonDifference.get() + entries.numberOfTerms.get()) # Just some test code to see if it works, which it doesnt
        except:
            pass

Я ожидаю, что когда я создам ссылку на класс Entries() в своем классе Buttons(), я смогу получить доступ к переменным, созданным в классе Entries(). Это не так, и я не могу понять, почему. Я просмотрел похожие исправления, и ни одно из них не работает.

Вам нужно определить переменные в __init__. Они не определяются без вызова функций.

Guy 31.05.2023 12:27

@Guy OP запускает эти другие методы в init, все должно быть в порядке ... но код, который они показали, использует Entries (), в то время как init принимает родителя, поэтому он должен сломаться еще до этого вывода

h4z3 31.05.2023 12:32

@tomasv 1. Вы выполняете Entries (), но инициализация в этом классе говорит, что вам нужно передать родителя - поэтому код должен завершиться с ошибкой перед строкой печати. Если он не падает, значит, вы используете другой код, который вы нам показали. 2. Удалите пробу и голое за исключением того, что вы скрываете ошибку. Пусть ошибка приведет к сбою вашего приложения и просто покажите нам, что она говорит.

h4z3 31.05.2023 12:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш класс Buttons не будет иметь прямого доступа к вашему классу Entries, если вы не передадите экземпляр entries (или хотя бы экземпляр entries) ему в __init__

Однако у него есть доступ к классу Program через parent

Подход, который я использовал в прошлом, выглядит следующим образом:

class Buttons(ttk.Frame):

    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.entries = parent.entries

Таким образом, ваш дочерний класс Buttons может получить доступ к атрибутам экземпляра Entries через их общий родительский класс через экземпляр entries, созданный в Program.__init__().

Вы можете обновить класс Entries__init__ аналогичным образом, чтобы он тоже мог получить доступ к атрибутам из parent

Я также склонен использовать подход, описанный в этом ответе, создавая словарь «общих» переменных в моем корневом классе приложения.

Ответ принят как подходящий

В вашем коде есть несколько проблем:

  • вы не должны создавать еще один экземпляр Entries внутри Buttons.calculate(). Предложить передать экземпляр Buttons при его создании;

  • функция self.calculate() фактически не вызывается в выражении command=lambda: self.calculate. Вместо этого используйте command=self.calculate. Та же проблема для command=lambda: self.clear;

  • если три входных данных являются числами, вам необходимо преобразовать их в числа, прежде чем выполнять расчет.

Обновленный код:

import tkinter as tk
from tkinter import ttk

class Program(tk.Tk):

    def __init__(self, title, size):
        super().__init__()
        self.title(title)
        self.geometry(f"{size[0]}x{size[1]}")

        # Program elements split into widget type
        self.entries = Entries(self)
        self.output = Output(self)
        self.buttons = Buttons(self, self.entries) ### pass self.entries to class Buttons

class Entries(ttk.Frame):

    def __init__(self, parent):
        super().__init__(parent)
        self.place(x = 0, y = 0)

        # Calling widget generator and placer functions
        self.entryGen()
        self.entryPlacer()

    def entryGen(self): # Create entry widgets
        self.firstTerm = ttk.Entry(self)
        self.commonDifference = ttk.Entry(self)
        self.numberOfTerms = ttk.Entry(self)

    def entryPlacer(self): # Place entry widgets
        self.firstTerm.pack()
        self.commonDifference.pack()
        self.numberOfTerms.pack()

class Buttons(ttk.Frame):

    def __init__(self, parent, entries): ### added argument entries
        super().__init__(parent)
        self.place(x = 200, y = 0)

        self.entries = entries  ### save the passed entries
        self.buttonGen()
        self.buttonPlacer()

    def buttonGen(self):
        self.clear = ttk.Button(self, text = "Clear", command = self.clear) ### remove lambda
        self.calculate = ttk.Button(self, text = "Calculate", command = self.calculate) ### remove lambda

    def buttonPlacer(self):
        self.clear.pack()
        self.calculate.pack()

    def clear(self):
        pass

    def calculate(self):
        try:
            ### convert inputs to numbers before calculation
            print(float(self.entries.firstTerm.get()) + float(self.entries.commonDifference.get()) + float(self.entries.numberOfTerms.get()))
        except Exception as ex:
            ### better show the execption
            print(ex)

Спасибо за помощь, работает отлично! Меня смущает, как он не заполняет переменные автоматически, когда вы вводите self.entries.firstTerm, почти как будто его не существует, но, тем не менее, он работает.

tomasv 01.06.2023 00:16

Другие вопросы по теме