Как обратиться к переменной класса python
Перейти к содержимому

Как обратиться к переменной класса python

  • автор:

Методы класса и статические методы

Когда мы реализовали класс Drob, нам нужна была функция, которая считает НОД для 2 чисел, чтобы сокращать дробь.

Это полезная функция. Хочется хранить ее внутри класса.

Но это не метод 1 экземпляра класса (одной дроби), он общий для всех дробей.

Этот метод не зависит ни от одной переменной ни в дроби, ни во всем классе дробей.

Такие методы называют статическими методами класса и пишут с @staticmethod перед определением метода.

Если статических методов в классе несколько, то у каждого нужно написать @staticmethod

Добавим в класс Drob статический метод nod.

Статический метод не относится к конкретной дроби. Он для всех дробей. У него нет self.

Статический метод не может написать self.переменная или self.функция, потому что у него нет self

Обращение к статической функции:

  • изнутри объекта класса: self или название класса
  • снаружи: название класса
class Drob(object): """ Дробь вида a/b""" def __init__(self, a=0, b=1): self.a = a self.b = b self.normalize() @staticmethod def nod(x, y): # нет self res = x % y while res > 1: x, y = y, res res = x % y return y def normalize(self): """ Приводит дробь вида 4/6 к 2/3""" k = Drob.nod(self.a, self.b) # можно self.nod self.a //= k self.b //= k def __str__(self): return '<>/<>'.format(self.a, self.b) # реализация функций __eq__, __lt__, __add__, __sub__, __mul__, # конец класса d1 = Drob(4, 6) print(d1) # 2/3 z = Drob.nod(123, 21) # класс.статический_метод print(z) # 3 

Еще один пример. В классе Segment1 отрезков по оси Х можно написать функцию пересечения отрезка с другим отрезком как функцию экземпляра класса crossed_with или как функцию не относящуюся ни к одному экземпляру (общую для всех экземпляров) is_crossed.

class Segment1(object): """Класс Segment1 описывает отрезки на оси Х""" def __init__(self, start=0, finish=0): # Эта функция вызывается, когда мы создаем новый объект класса. # self - это название переменной, которая указвает на сам объект. self.start = start # переменная объекта self.finish = finish def __str__(self): return '<> <>'.format(self.start, self.finish) def crossed_with(self, other): # метод экземпляра класса """ Пересекается этот отрезок self с другим отрезком other? """ if self.finish < other.start or other.finish < self.start: return False return True @staticmethod def is_crossed(seg1, seg2): # статический метод класса (нет self) """ Пересекаются ли отрезки seg1 и seg2? """ if seg1.finish < seg2.start or seg2.finish < seg1.start: return False return True # вызываем метод экземпляра класса и статический метод класса: s1 = Segment1(2, 5) s2 = Segment1(3, 7) print(s1.crossed_with(s2)) # метод экземпляра класса print(Segment1.is_crossed(s1, s2)) # статический метод класса 

Переменные класса

Пусть мы делаем класс окружность. В каждой окружности есть радиус, (x, y) — координаты центра окружности. У окружности можно посчитать радиус и периметр. Для их вычсления нужно число пи (3.14. )

Вопрос — к какой именно окружности принадлежит число пи? Ни к какой. Оно характеризует все окружности сразу.

Значит, число пи должно храниться не в переменных экземпляра класса (1 окружность), а в переменных всего класса (объект класса).

Переменные класса пишутся или вне методов в классе, или внутри метода как класс.переменная

Посчитаем, сколько экземпляров класса Drob создали за время работы программы. Можно создать глобальную переменну counter. Но лучше сделать ее переменной класса.

class Segment1(object): """Класс Segment1 описывает отрезки на оси Х""" counter = 0 # еще не было создано ни одной окружности def __init__(self, start=0, finish=0): # Эта функция вызывается, когда мы создаем новый объект класса. # self - это название переменной, которая указвает на сам объект. self.start = start # переменная объекта self.finish = finish Segment1.counter += 1 @classmethod def how_many(cls): return cls.counter # конец класса s1 = Segment1(2, 5) s2 = Segment1(3, 7) print(Segment1.how_many()) # вызов метода класса по имени класса print(s1.how_many()) # вызов метода класса по имени класса 

Переменная counter — одна на весь класс. Общая. Каждый экземпляр класса (1 дробь) может в нее писать по ссылке Segment1.counter

Чем отличается @staticmethod от @classmethod ?

В методе класса how_many:

  • есть аргумент cls (класс Drob). Если self означает 1 дробь (объект с полями и методами), то cls — объект класса (один на класс Drob, описывает этот класс).
  • Обращаться к полям и методам класса можно или по имени класса Drob.counter или по переменной cls.counter;
  • Вызывается этот метод по имени класса или ссылки на экземпляр класса. Лучше всегда обращайтесь к переменной по имени класса.

Делаем экземпляр класса

Напишем функцию read(line), которая будет из строки делать отрезок.

Хотим, чтобы Segment1.read(‘2, 5’) создал и вернул Segment1(2, 5)

Функция read всего класса, а не 1 отрезка. Значит, это или staticmethod, или classmethod.

Если функция всего класса возвращает экземпляр класса, делайте ее classmethod (Позже объясним зачем, когда будем изучать наследование классов).

class Segment1(object): . @classmethod def read(cls, line): start, finish = map(int, line.split(',')) t = Segment1(start, finish) return t # или сразу return Segment1(start, finish) - можно обойтись без переменной t 

Если есть ссылка на объект всего класса, можно заменить вызов Segment1(..) на cls(..)

class Segment1(object): . @classmethod def read(cls, line): start, finish = map(int, line.split(',')) return cls(start, finish) # cls - ссылка на весь класс 

Итого

class A(object): class_var = 2 def __init__(self, x): self.x = x @classmethod def foo(cls): . @staticmethod def bzz(): . a = A() A.class_var = 33 A.foo() A.bzz() 
  • Класс — тоже объект. У класса могут быть переменные и методы. Класс А, переменная class_var, метод foo.
  • переменная класса пишется вне всех функций внутри класса; class_var
  • обращаются к переменной класса по класс.переменная; A.class_var
  • метод класса не работает с 1 экземпляром класса, у него нет self. def foo(cls):
  • метод класса работает с объектом класса, на него ссылаются через cls ;
  • конструктор можно вызвать через _cls(аргументы) cls(7)
  • к методу класса можно обратиться через имя класса A.foo()
  • если метод не для 1 дроби, а для всех и ему не нужны переменные класса, то делаем @staticmethod

Задачи

Drob

Drob.nod, Drob.read

В класс Drob дописать статический метод nod и метод класса read.

Drob — калькулятор 2 дробей

Реализовать калькуляр дробей, который вычисляет сумму и разность дробей, заданных по формату:

1/3 + 1/6 = 

Нужно напечатать ответ: 1/2

Drob — сумматор многих дробей

Как в предыдущей задаче. Только дробей может быть не 2, а больше. Только + и -.

Drob — калькулятор без скобок

Напишите калькулятор, который считает дроби.

Нужно 2 стека. Стек дробей stack_drob и стек операций (+, -, *) stack_op.

Пусть у каждой операции будет приоритет.

prior = # символ операции : приоритет операции

Полжить в стек можно функцию append работы с list, а взять функцией pop() .

Сначала положить в стек операций =. (Кладем кортеж (‘=’, 0) — символ и приоритет. Такие пары хранятся в стеке операций. Как считать выражение:

  • если дробь, положить в стек дробей.
  • если операция:
    • если в стеке операция с меньшим приоритетом, положить нашу операцию в стек операций;
    • иначе пока подходящие операции не закончатся,
      • достать операцию из стека операций;
      • достать 2 дроби из стека дробей;
      • посчитать результат «дробь операция дробь» и положить его в стек дробей.

      В конце должен быть пустой стек операций и 1 дробь в стеке дробоей — результат работы калькулятора.

      Кнаты, сикли, галеоны

      У волшебников свои деньги. Это галеоны (galeon), сикли (sicle), кнаты (knut).

      • 1 галеон = 17 сиклей
      • 1 сикль = 29 кнатов

      Написать класс WMoney, который хранит сумму в кнатах, а печатает по формату 1 galeon 5 sicle 10 knut.

      В классе написать метод read(str), который из строки ‘1 galeon 5 sicle 10 knut’ делает WMoney(galeon=1, sicle=5, knut=10)

      Timer — дописать

      Кнаты, сикли, галеоны

      Чек в магическом магазине со сдачей.

      Автомат по продаже билетов

      Переменные класса — список допустимых монет.

      Электричка на Марсе

      Модифицировать задачу дополнения расписания, при условии, что планета не Земля, и там другое количество минут в 1 часе и часов в сутках (может дробное. )

      results matching » «

      No results matching » «

      Как обратиться к переменной другого класса?

      Есть классы MyWidget(QMainWindow) и ThreadClassCheck(QtCore.QThread) .
      В MyWidget() открывается интерфейс с двумя полями ввода и одной кнопкой.
      После нажатия на кнопку из первого (верхнего) поля ввода это слово переносится во второе поле ввода (при этом в первом это слово также остается). Как можно в классе ThreadClassCheck(QtCore.QThread) обратиться к значению этих двух полей из класса MyWidget() ? Дизайн t.ui:

        MainWindow   0 0 491 276   MainWindow     210 190 93 31   кнопка     130 40 321 31      50 40 51 31   font: 12pt "MS Shell Dlg 2";  Ввод     50 120 71 31   font: 12pt "MS Shell Dlg 2";  Вывод     130 120 321 31       0 0 491 26       

      main.py:

      from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5 import QtCore from PyQt5 import uic import sys import time class ThreadClassCheck(QtCore.QThread): signal = QtCore.pyqtSignal(str) def __init__(self, checkword, parent=None): super(ThreadClassCheck, self).__init__(parent) self.is_going = True self.checkword = checkword def display(self): print('ниже выведем первое поле') print(self.lineEditInput.text()) def run(self): while True: # как здесь получить переменную значение из двух полей ввода? # self.text1 = self.lineEditInput.text() # self.text2 = self.lineEdit_2Output.text() # в интерфейсе, но не в классе ThreadClass ex = MyWidget() # экземпляр интерфейса ThreadClassCheck.display(ex) # такой вызов тоже не работает, пустая строка time.sleep(3) sms = "check" self.signal.emit(sms) def stop(self): self.is_going = False self.terminate() class MyWidget(QMainWindow): def __init__(self): super().__init__() uic.loadUi('t.ui', self) self.pushButton.clicked.connect(self.btn) self.text2 = self.lineEdit_2Output.text() self.text1 = self.lineEditInput.text() def btn(self): print('кнопка нажата, данные из первой строки:', self.text1) print('кнопка нажата, данные из второй строки:', self.text2) self.lineEdit_2Output.setText(self.text1) # из первого поля ввода переносим во второй def except_hook(cls, exception, traceback): sys.__excepthook__(cls, exception, traceback) if __name__ == '__main__': app = QApplication(sys.argv) ex = MyWidget() ex.show() sys.excepthook = except_hook sys.exit(app.exec_()) 

      Попробовал через экземпляр, но почему-то выводит пустую строку.

      Как обратиться к переменной, находящейся внутри класса

      Вытащить переменную без связки с Backtrader (в тестовом режиме и переменными в виде вручную заданных списков) одним из возможных методов по следующему примеру получается:

      # 1 f = someClass(object) f.var1 = [1,2,3] f.var2 = 'asdf' someClass(f) 
      # 2 XClass = someClass() XClass.close 

      Через **kwargs тоже вытаскивается, но этот вариант даже не рассматриваю, т.к. списков очень много. Получить доступ к self.close находясь внутри класса возможно. Но принципиально нужно вытащить close как в представленном коде. Что я не так делаю?

      Как в python обратиться к переменной родительского класса?

      Грубо говоря функция sum должна написать «11»
      Я может где то не верно выразился.
      Мне это нужно для программки на PyQt. Я из главного окна открываю вручную нарисованные диалоговые окошки, в которых запрашиваю различные данные, и хочу что бы эти данные сохранились в главном окне. (Возможно вы меня поймете)

      • Вопрос задан более трёх лет назад
      • 6109 просмотров

      Комментировать
      Решения вопроса 1

      Не очень понял, зачем Вам это надо, но минимальные исправления ниже, причем варианты для Dialog1 и Dialog2 разные, без доп.информации не знаю, как лучше.

      class Main(object): # основная функция def __init__(self): self.ab = AB() # создаем экзмпляр класса с переменными d1 = Dialog1(self.ab) # Создаем экзэмпляр класса который должен поменять переменную ab.a d2 = Dialog2(self) # Создаем экзэмпляр класса который должен поменять переменную ab.b def sum(self): c = self.ab.a + self.ab.b print(c) class Dialog1(object): def __init__(self, parent): parent.a = 5 # . Пытаюсь поменять значение в переменной созданом в родительском классе Main class Dialog2(object): def __init__(self, parent): parent.ab.b = 6 # . Пытаюсь поменять значение в переменной созданом в родительском классе Main class AB(object): a = 1 b = 2 m = Main() print(m.ab.a) print(m.ab.b)

      Ответ написан более трёх лет назад
      Нравится 1 1 комментарий
      Александр Рублев @Meller008 Автор вопроса

      Спасибо это работает. Причем до этого догадаться было не сложно. Специально для вас нарисавал ПРИМЕРНУЮ картинку замысла. (Если вдруг интересно) joxi.ru/KAx9px7U4YG3jr.jpg

      Ответы на вопрос 2
      Родительский класс подразумевает наследование. У вас его нет.
      Ответ написан более трёх лет назад
      Александр Рублев @Meller008 Автор вопроса
      Да я понял что я неправильно выразился. Я просто пытался поподробнее объяснить.
      Vov Vov @balamut108
      super — это супер, см. видос на эту тему для Python 3: pythonz.net/videos/34
      Ответ написан более трёх лет назад
      Комментировать
      Нравится Комментировать
      Ваш ответ на вопрос

      Войдите, чтобы написать ответ

      python

      • Python
      • +1 ещё

      Почему парсер не нажимает кнопку?

      • 1 подписчик
      • только что
      • 2 просмотра

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *