Вызов переменных и функций за пределами класса

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1
Добрый день! Столкнулся с проблемой вызова отдельных переменных из различных функций или самих функций из класса в основной код.
Получается, чтобы работать с переменными, мне нужно весь код писать внутри класса (объект окна pyqt5).
Но ведь это "грибы"! Неужели нет способа вызвать локальные переменные или сами функции из под класса в глобальную часть кода?
Ищу в литературе, уже две книги отлетело, но информации по этому нет. Штудирование форумов тоже не принесло ответа, хотя нашёл много полезного.
Понятно, что сами переменные можно вызвать извне, если в функции прописать return, но за пределами класса эти функции не видны.
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 672
478
83
Понятно, что сами переменные можно вызвать извне, если в функции прописать return, но за пределами класса эти функции не видны.
как же не видны, в питоне все публичное...
пример
Python:
import sys
from PyQt5.QtWidgets import QWidget, QApplication


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.a = 5
        self.gui()

    def gui(self):
        self.setGeometry(300, 300, 300, 200)
        self.show()

    # геттер для получения переменной из класса
    def get_a(self):
        return self.a


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    print(mw.a)        # получили переменную из класса
    print(mw.get_a())  # геттер для получения переменной из класса
    sys.exit(app.exec_())


в qt не обязательно писать через классы...
пример
Python:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit


def btn_click():
    sender = w.sender()
    line_edit.insert(sender.text() + " нажата")

app = QApplication(sys.argv)

w = QWidget()
btn = QPushButton("Кнопка", w)
btn.clicked.connect(btn_click)
line_edit = QLineEdit(w)

line_edit.move(30, 30)
w.resize(250, 150)
w.move(300, 300)
btn.move(50, 50)
w.show()

sys.exit(app.exec_())
как видите, здесь нет классов, код написан в процедурном стиле...

но qt - это объектно ориентированный фреймворк, это значит, если вы хотите использовать какие то плюшки из qt, вам нужно унаследоваться от определенного класса...
к примеру, хотим использовать qt-шные потоки, нам нужно унаследоваться от класса QThread (на самом деле не обязательно, но речь не об этом), в процедурном стиле у вас это не получиться сделать...

дальше
мне нужно весь код писать внутри класса (объект окна pyqt5).
это и есть инкапсуляция - один из трех основных принципов ООП (объектно ориентированное программирование)...
классу не нужно то, что происходит снаружи, он самодостаточен...
это вам что то нужно от класса...
и не обязательно писать все в одном классе, можете сделать базовый класс, и от него наследоваться и добавлять нужный функционал...


Неужели нет способа вызвать локальные переменные или сами функции из под класса в глобальную часть кода?
вы немного не понимаете ООП...
переменные в классе приватные (но в питоне нет), это значит что извне к ним доступа нет, это сделано в целях безопасности и стабильности кода...
если вы хотите поменять переменную в классе извне, делаются сеттеры (set метод), который меняет переменную внутри класса, обычно с ограничениями по каким то параметрам...
если вам нужно получить переменную из класса извне, делаются геттеры (get метод), который возвращает переменную...
в хорошем ООП коде нет глобальных переменных, и классу не нужно раздавать свои переменные в глобальную часть кода...
методы (функции) класса вы можете вызвать, если они публичные (в питоне все публичное)...


Ищу в литературе, уже две книги отлетело, но информации по этому нет
вы не знаете чего вы ищите, советую почитать про ООП, не про определенный язык, а в целом про ООП...
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 672
478
83
Возник ещё вопрос:
Если в классе некоторые переменные присваиваются не во время инициализации, а в других методах, то почему при вызовах всё равно выдаётся ошибка Attribute error?
Внутри класса в методах задаю всё через "self.", что напрямую означает название класса (ну pycharm по крайней мере так говорит).
Видимо я ещё что-то не знаю и упускаю.

Пример:
Python:
class _1st(object):
    def __init__(self):
        print("Ya rodilsya")

    def var2(self):
        self.v = "Ok"

    def vivod(self):
        return self.v

class _2nd(object):
    def __init__(self):
        print("Nu poprobui")
        pervaya = _1st()
        self.p = pervaya.vivod()
        self.printui()

    def printui(self):
        print(self.p)

if __name__ == "__main__":
    w = _2nd()
    print("Loaded")
ошибка возникает, потому то переменной self.v не существует, пока вы ее не определите (в питоне это значит - не присвоите ей значение), в вашем коде переменная определяется в методе var2, его нужно сначала вызвать, что бы определить переменную, а потом уже возвращать ее...
пример
Python:
class _1st(object):
    def __init__(self):
        print("Ya rodilsya")

    def var2(self):
        self.v = "Ok"

    def vivod(self):
        return self.v

class _2nd(object):
    def __init__(self):
        print("Nu poprobui")
        pervaya = _1st()
        pervaya.var2()
        self.p = pervaya.vivod()
        self.printui()

    def printui(self):
        print(self.p)

if __name__ == "__main__":
    w = _2nd()
    print("Loaded")


Внутри класса в методах задаю всё через "self.", что напрямую означает название класса
слово self показывает питону, что нужно искать эту переменную или этот метод внутри класса (грубо говоря это указатель класса на самого себя), вместо self можно написать любое другое слово, например в с++ это слово - this, но в питоне принято писать self...
 
Последнее редактирование:

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 672
478
83
только значение этой переменной определяется функцией, которая вызывается от нажатия одной из двух кнопок
ну вынесите определение переменной в другой метод, а по кнопке просто получайте его...
переменная выгружается из памяти
в питоне переменная удаляется, когда перестают существовать все ссылки на нее...
Могу скинуть основной код
ну кидайте, посмотрю
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 672
478
83
у вас с логикой программы большие проблемы...

при запуске программы вы делаете экземпляр класса Mainy, кнопка у вас в классе Mainy, при нажатии на кнопку вы определяете переменную aotb и делаете экземпляр класса result, в конструкторе которого вы делаете экземпляр класса Calcing, в конструкторе которого вы делаете новый экземпляр класса Mainy и вызываете метод siding из этого нового экземпляра, в котором переменная aotb еще не определена, ее не существует там...

я не понял смысла программы, что вы считаете, но зачем вам столько классов? из которых вы прыгаете туда сюда? даже на словах видно, что вы сделали круг по классам...

если вам и правда необходима такая схема, то методы вызывайте из основного экземпляра, который вы определили после if __name__ == "__main__":

немного подправил, что бы при нажатии на кнопки мы получали данные из полей ввода, а не в конструкторе, когда там ничего нет...
Python:
....

class Mainy(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Mainy, self).__init__(parent)
        self.setupUi(self)
        self.port_btn.clicked.connect(self.port_btn_clicked)
        self.stbd_btn.clicked.connect(self.stbd_btn_clicked)
        # self.li1 = self.line_1.text()
        # self.li2 = self.line_2.text()
        # self.li3 = self.line_3.text()
        # self.li4 = self.line_4.text()

    def port_btn_clicked(self):
        self.li1 = self.line_1.text()
        self.li2 = self.line_2.text()
        self.li3 = self.line_3.text()
        self.li4 = self.line_4.text()
        print("port pressed")
        self.gut_checks()
        print("port -> gut passed")
        self.aotb = "Port"
        print("port -> aotb assigned")
        f = result()
        print("result UI loaded")
        # f.show()

    def stbd_btn_clicked(self):
        self.li1 = self.line_1.text()
        self.li2 = self.line_2.text()
        self.li3 = self.line_3.text()
        self.li4 = self.line_4.text()
        print("stbd pressed")
        self.gut_checks()
        print("stbd -> gut passed")
        self.aotb = "Starboard"
        print("stbd -> aotb assigned")
        f = result()
        print("result UI loaded")
        # f.show()
      
....


и тут мы обращаемся к первому экземпляру, который был создан при запуске программы...
Python:
....

class Calcing(object):
    def __init__(self, parent=None):
        # super(Calcing, self).__init__(parent)
        # m = Mainy()
        lines = w.lines()
        l1 = lines[0]
        l2 = lines[1]
        l3 = lines[2]
        l4 = lines[3]
        side = w.siding()
        vspd = l1
        vdir = l2
        rspd = l3
        rdir = l4
      
....


дальше у вас ошибка типов в вычислениях в этой строке self.tspd = math.sqrt((vspd ** 2 + rspd ** 2 - 2 * vspd * rspd * math.cos(math.radians(rdir)))), я не стал разбираться, простите...
 

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1

Благодарю вас за очень развёрнутый ответ с примерами! Пойду изучать ООП
 

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1
как же не видны, в питоне все публичное...
пример

Возник ещё вопрос:
Если в классе некоторые переменные присваиваются не во время инициализации, а в других методах, то почему при вызовах всё равно выдаётся ошибка Attribute error?
Внутри класса в методах задаю всё через "self.", что напрямую означает название класса (ну pycharm по крайней мере так говорит).
Видимо я ещё что-то не знаю и упускаю.

Пример:
Python:
class _1st(object):
    def __init__(self):
        print("Ya rodilsya")

    def var2(self):
        self.v = "Ok"

    def vivod(self):
        return self.v

class _2nd(object):
    def __init__(self):
        print("Nu poprobui")
        pervaya = _1st()
        self.p = pervaya.vivod()
        self.printui()

    def printui(self):
        print(self.p)

if __name__ == "__main__":
    w = _2nd()
    print("Loaded")
 

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1
ошибка возникает, потому то переменной self.v не существует, пока вы ее не определите (в питоне это значит - не присвоите ей значение)...

Проблема в том, что этот метод выполняется заранее, присваивая нужную переменную, затем в его конце идёт вызов другого класса, который производит расчёты, ссылаясь на переменную первого класса. И всё бы ничего, да вот только значение этой переменной определяется функцией, которая вызывается от нажатия одной из двух кнопок (левый / правый, грубо говоря).
Я так понимаю, что переменная выгружается из памяти, когда идёт исполнение другого класса.
В прошлом сообщение постарался набросать простенький код, чтобы вы не мучились с большим, однако он оказался неудачным примером.
Могу скинуть основной код, если у вас будет желание взглянуть.
 

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1
ну кидайте, посмотрю

К сожалению, код получился большой, но в основном из-за строчек с интерфейсом. В pycharm через дебаггер сразу показывает заковырку.
На всякий случай: строка 201

Залил код на pastebin:
 

hurtZ

Новичок
Пользователь
Окт 13, 2021
10
0
1
у вас с логикой программы большие проблемы...

при запуске программы вы делаете экземпляр класса Mainy...

Почитал немного про ООП и, так как это для меня нечто новое, решил воспользоваться принципом "больше классов богу классов! " ))

Примерно понял куда копать благодаря вам, буду перестраивать код.
Основные моменты, надеюсь, усвоил.

Спасибо большое за помощь!!!
 

Форум IT Специалистов