Перейти к содержимому

Как обратиться к методу другого класса python

  • автор:

Как из метода класса вызвать метод другого класса, когда оба внутри третьего класса?

Или я просто не вкурил, как вызвать вышележащий namespace. Или я делаю нечто нехорошее, за что бьют канделябром.

Зачем мне это нужно: в программе леплю класс, абстрагирующий от остального кода GUI. Внутри него должно крутится все связанное с *graphical toolkit name*. Два окна, два класса. В одном прилетает callback, оно себя закрывает и должно вызывать show для другого окна.

Gregon ★
02.12.12 16:33:12 MSK

1) передай в B инстанс a параметром. Я за этот вариант.

2) сделай глобальную переменную a (см. оператор global).

PS Кстати, перменные глобальны только в пределах одного модуля.

true_admin ★★★★★
( 02.12.12 16:42:22 MSK )
Ответ на: комментарий от true_admin 02.12.12 16:42:22 MSK

Сделал передачу инстанса в __init__(), заработало, спасибо.

Другие варианты как подобные вещи разруливать существуют? Имхо, если есть сотня окон то начинается трэш и угар: они создаются и уничтожаются. Придется создавать список и регулярно обновлять его. Выглядит как костыль. А глобальные переменные всегда предавались анафеме)

Gregon ★
( 02.12.12 16:54:30 MSK ) автор топика
Ответ на: комментарий от Gregon 02.12.12 16:54:30 MSK

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

А список с регулярными обновлениями делается просто, посмотри weakref модуль. Дальше в __init__ просто в этот контейнер запихиваешь self.

import weakref container = weakref.weakSet() class Test: def __init__(self): container.add(self) 

true_admin ★★★★★
( 02.12.12 17:02:10 MSK )

Может тебя так устроит?

class A(object): def func(self): print "it works" class B(object): def func2(self, ns): ns.a.func() class C(object): def __init__(self): self.a = A() self.b = B() self.b.func2(self) if __name__ == '__main__': c = C() 

k0valenk0_igor ★★★
( 02.12.12 17:07:31 MSK )
Ответ на: комментарий от true_admin 02.12.12 17:02:10 MSK

Callback прилетает после нажатия кнопки в визарде первой настройки, с ним прилетает исключительно инфа «закрой окно, я закончил».

Gregon ★
( 02.12.12 17:15:18 MSK ) автор топика
Ответ на: комментарий от Gregon 02.12.12 17:15:18 MSK

я думаю ты что-то не то делаешь. Я надеюсь ты не пытаешься написать абстрактную обёртку для любого *graphical toolkit name*?

true_admin ★★★★★
( 02.12.12 17:17:25 MSK )
Ответ на: комментарий от k0valenk0_igor 02.12.12 17:07:31 MSK

Отлично, так тоже работает и теперь у меня есть доступ к неймспейсу суперкласса, большое спасибо.

Gregon ★
( 02.12.12 17:20:31 MSK ) автор топика

class A(object): def func(self): print "it works" class B(object): def func2(self): self.a.func() class C(object): def __init__(self): a = A() b = B() b.a = a b.func2() if __name__ == '__main__': c = C() 

k0valenk0_igor ★★★
( 02.12.12 17:21:15 MSK )
Ответ на: комментарий от Gregon 02.12.12 17:20:31 MSK

Да не за что. Удачи, коллега!)))

k0valenk0_igor ★★★
( 02.12.12 17:22:09 MSK )
Ответ на: комментарий от Gregon 02.12.12 17:20:31 MSK

теперь у меня есть доступ к неймспейсу суперкласса

Что ты называешь «суперклассом»?

tailgunner ★★★★★
( 02.12.12 17:22:18 MSK )
Ответ на: комментарий от true_admin 02.12.12 17:17:25 MSK

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

Gregon ★
( 02.12.12 17:22:59 MSK ) автор топика
Ответ на: комментарий от tailgunner 02.12.12 17:22:18 MSK

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

Gregon ★
( 02.12.12 17:26:39 MSK ) автор топика

Как из метода класса вызвать метод другого класса, когда оба внутри третьего класса?

как минимум так:

class A(object): def func(self): print "it works" class B(object): def func2(self, a): a.func() class C(object): def __init__(self): a = A() b = B() b.func2(a) if __name__ == '__main__': c = C() 

AGUtilities ★★★
( 02.12.12 17:26:51 MSK )
Ответ на: комментарий от Gregon 02.12.12 17:22:59 MSK

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

я так и думал. Забей на это потому что:

1) не справишься

2) это бессмысленная задача, 99% времени всё равно будешь сидеть либо на qt, либо на gtk

4) делать абстрактный универсальный код «на все случаи жизни» это классическая ошибка программистов. Протрахаешься неделю/месяц и забьёшь, а результата не получишь

5) даже если сделаешь костыль он будет страшен потому что тулкиты между собой отличаются не только именами функций, но ещё архитектурой. Поэтому у тебя будет, по-сути, написаны очень разные обёртки с одним API. Так сделай сразу как надо: разбей свою программу на низкоуровневую библиотеку и к ней напиши несколько интерфейсов.

Короче, потрать время с большей пользой.

true_admin ★★★★★
( 02.12.12 18:07:20 MSK )
Последнее исправление: true_admin 02.12.12 18:07:58 MSK (всего исправлений: 1)

Как использовать метод класса в другом классе python?

Для этого нужно указать этот класс в качестве родителя по отношению к текущему классу. Например, если в нашем классе MyClass мы хотим использовать метод method класса Parent :

class MyClass(Parent): # наследуем от класса Parent pass MyClass.method # # метод method родительского класса доступен для использования 

Как вызвать метод из родительского класса python?

Для вызова метода из родительского класса в Python есть два способа:

  1. Явное обращение к методу предка
  2. Функция super()
class Counter: def __init__(self): self.value = 0 def inc(self): self.value += 1 def dec(self): self.value -= 1 # Создаем класс-потомок, при вызове inc увеличивающих значение дважды # Вариант 1 - с прямым обращением к предку: class DoubleCounter(Counter): def inc(self): Counter.inc(self) # явно обращаемся к методу класса предка Counter.inc(self) # и передаем ссылку на экземпляр # Вариант 2 - с применением функции super(): class DoubleCounter(Counter): def inc(self): super().inc() super().inc() num = DoubleCounter() num.value # 0 num.inc() # В обоих случаях, наследованный метод inc() будет работать одинаково num.value # 2 

Функция super() названа в честь названия класса-предка: «superclass». Потому что благодаря ей мы получаем ссылку на атрибут предка и заменяем обращение self , создавая таким образом связанный с текущим классом метод, который будет полноценной «оригинальной версией» из класса-предка. При чем если предок сменится, то super в описании класса учтет изменения, и мы получим доступ к поведению нового предка.

Методы классов. Параметр self

Мы продолжаем изучать ООП языка Python. Как я говорил на первом занятии, класс может содержать свойства (данные) и методы (функции). Благодаря методам внутри класса можно реализовывать самые разные алгоритмы, то есть методы – это действия. Именно поэтому, в названиях методов используют глаголы, например:

set_value, get_param, start, stop, и т.п.

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

color, size, x, y, и т.п.

Рекомендуется придерживаться этого простого правила.

Давайте, для примера объявим метод set_coords в классе Point, который будет просто выводить в консоль сообщение «вызов метода set_coords»:

class Point: color = 'red' circle = 2 def set_coords(self): print("вызов метода set_coords")

Здесь сразу бросается в глаза вот этот параметр self, который автоматически прописывает интегрированная среда. Зачем он здесь, если мы пока ничего не собираемся передавать этому методу? Давайте его уберем! Пока никаких проблем не возникло. Мало того, мы можем его вызвать из класса Point:

Point.set_coords()

и все будет работать без ошибок. Здесь мы видим, как вызываются методы класса. Все довольно очевидно. Записываем имя класса (Point), и через точку указываем имя метода. В конце обязательно прописываем круглые скобки, так как это оператор вызова функций. И, так как метод – это функция класса, то для вызова метода используется тот же оператор, что и для вызова функций.

В результате, мы получили класс, в котором два свойства и один метод. Далее, создадим экземпляр этого класса:

pt = Point()

И, как мы с вами говорили, через объект pt можно обращаться ко всем атрибутам класса Point, в том числе и к методу set_coords:

pt.set_coords

Этот атрибут ссылается на объект-функцию, которую мы определили в классе Point. Попробуем ее вызвать:

pt.set_coords()

Видим ошибку, что в метод set_coords при вызове передается один аргумент, а он у нас определен без параметров. Дело в том, что когда мы вызываем методы класса через его объекты, то интерпретатор Python автоматически добавляет первым аргументом ссылку на объект, из которого этот метод вызывается.

Поэтому, если мы хотим внутри класса определить метод, который можно было бы вызывать из его экземпляров, то дополнительно прописывается первый параметр, обычно, с именем self:

class Point: color = 'red' circle = 2 def set_coords(self): print("вызов метода set_coords " + str(self))

Еще раз, параметр self будет ссылаться на экземпляр класса, из которого вызывается метод. Зачем это надо? Сейчас узнаете. После этого дополнения мы уже не сможем вызвать данный метод через класс без указания первого аргумента:

Point.set_coords()

но можем через его объекты:

pt.set_coords()

То есть, когда метод вызывается через класс, то Python автоматически не подставляет никаких аргументов. А когда вызов идет через экземпляры класса, то первый аргумент – это всегда ссылка на экземпляр. Данный момент нужно знать и помнить.

Но мы все же можем вызвать метод set_coords и через класс, если явно передадим ссылку на объект pt, следующим образом:

Point.set_coords(pt)

Именно это на автомате делает Python, когда вызов осуществляется через объекты классов.

Так зачем понадобилось такое поведение? Дело в том, что метод класса – это тоже его атрибут и когда создаются экземпляры класса, то метод становится общим для всех объектов и не копируется в них. Фактически, только благодаря параметру self мы «знаем» какой объект вызвал данный метод и можем организовать с ним обратную связь.

Например, пусть метод set_coords задает координаты точек для текущего объекта. Тогда, мы пропишем в нем два дополнительных параметра и через self в самом экземпляре класса создадим (либо переопределим) два свойства:

class Point: color = 'red' circle = 2 def set_coords(self, x, y): self.x = x self.y = y

В результате, при вызове метода:

pt.set_coords(1, 2) print(pt.__dict__)

в объекте pt будут созданы два свойства x, y со значениями 1 и 2. Вот для чего нужен этот параметр self. Если в программе создать еще один объект:

pt2 = Point()

и через него вызвать тот же самый метод:

pt2.set_coords(10, 20) print(pt2.__dict__)

То увидим, что свойства x, y со значениями 10 и 20 были созданы только в нем (в его пространстве имен) и никак не связаны с координатами другого объекта pt или классом Point. То есть, через self мы работаем с конкретным объектом, из которого был вызван данный метод.

Конечно, в классах мы можем прописывать произвольное количество методов. Например, определим еще один, который будет возвращать координаты точки в виде кортежа значений:

class Point: color = 'red' circle = 2 def set_coords(self, x, y): self.x = x self.y = y def get_coords(self): return (self.x, self.y)

И ниже в программе можем вызвать его:

print(pt.get_coords())

Интересно, что так как имя метода – это атрибут класса, то мы можем обратиться к нему через знакомую нам уже функцию:

res = getattr(pt, 'get_coords') print(res)

Видим, что это ссылка на объект-функцию. А раз так, то ничто нам не мешает ее здесь вызывать:

print(res())

Конечно, так делают очень редко. Обычно используют синтаксис через точку. Я привел это, чтобы еще раз подчеркнуть, что имена методов – это те же самые атрибуты, просто они ведут не на данные, а на функции. Во всем остальном они схожи с атрибутами-данными класса.

Заключение

Итак, на этом занятии вы должны были узнать, как определяются простые методы класса, за что отвечает параметр self и как происходит обращение к методам и их вызов. Если все это понятно, то смело переходите к следующему занятию, где мы продолжим эту тему.

Видео по теме

Концепция ООП простыми словами

#1. Классы и объекты. Атрибуты классов и объектов

#2. Методы классов. Параметр self

#3. Инициализатор __init__ и финализатор __del__

#4. Магический метод __new__. Пример паттерна Singleton

#5. Методы класса (classmethod) и статические методы (staticmethod)

#6. Режимы доступа public, private, protected. Сеттеры и геттеры

#7. Магические методы __setattr__, __getattribute__, __getattr__ и __delattr__

#8. Паттерн Моносостояние

#9. Свойства property. Декоратор @property

#10. Пример использования объектов property

#11. Дескрипторы (data descriptor и non-data descriptor)

#12. Магический метод __call__. Функторы и классы-декораторы

#13. Магические методы __str__, __repr__, __len__, __abs__

#14 Магические методы __add__, __sub__, __mul__, __truediv__

#15. Методы сравнений __eq__, __ne__, __lt__, __gt__ и другие

#16. Магические методы __eq__ и __hash__

#17. Магический метод __bool__ определения правдивости объектов

#18. Магические методы __getitem__, __setitem__ и __delitem__

#19. Магические методы __iter__ и __next__

#20. Наследование в объектно-ориентированном программировании

#21. Функция issubclass(). Наследование от встроенных типов и от object

#22. Наследование. Функция super() и делегирование

#23. Наследование. Атрибуты private и protected

#24. Полиморфизм и абстрактные методы

#25. Множественное наследование

#26. Коллекция __slots__

#27. Как работает __slots__ с property и при наследовании

#28. Введение в обработку исключений. Блоки try / except

#29. Обработка исключений. Блоки finally и else

#30. Распространение исключений (propagation exceptions)

#31. Инструкция raise и пользовательские исключения

#32. Менеджеры контекстов. Оператор with

#33. Вложенные классы

#34. Метаклассы. Объект type

#35. Пользовательские метаклассы. Параметр metaclass

#36. Метаклассы в API ORM Django

#37. Введение в Python Data Classes (часть 1)

#38. Введение в Python Data Classes (часть 2)

#39. Python Data Classes при наследовании

© 2024 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта

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

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