Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 5, 2010 23:55:41

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

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

Daevaorn, не совсем уловил. Даже если я заведу такой класс и унаследую от него всех подписчиков, то как это поможет мне вызвать методы подписки? Мне вообще сначала показалось, что это довольно типовая задача и ее решение должно быть довольно тривиальным, если не очевидным. Что-то видимо не так я делаю.



Отредактировано (Ноя. 5, 2010 23:56:08)

Офлайн

#2 Ноя. 6, 2010 02:08:47

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

Soteric
Чтобы подписать класс, нужно вызвать его метод. Как вызвать метод класса, если заранее неизвестно имя класса?
Тоесть какие классы должны реагировать на событие ты знаешь, но имя неизвестно? :)

Ок, сделай подписку иначе. Пускай класс Publisher, который публикует событие делегирует подписку Subscriber-ам.

# coding: utf8


class Publisher(object):

subscribers = []

@classmethod
def notify(cls):
for subscriber in cls.subscribers:
subscriber.woohoo()


class Subscriber(object):

@classmethod
def attach(cls, publisher):
publisher.subscribers.append(cls)

class Subscriber_Dima(Subscriber):

@classmethod
def woohoo(cls):
print 'Dima!'


class Subscriber_Ira(Subscriber):

@classmethod
def woohoo(cls):
print 'Ira!'

Subscriber_Ira.attach(Publisher)
Subscriber_Dima.attach(Publisher)
Publisher.notify()



Офлайн

#3 Ноя. 6, 2010 02:32:36

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

Нет, не совсем. Про классы ничего неизвестно. То есть

Subscriber_Ira.attach(Publisher)
Subscriber_Dima.attach(Publisher)

если бы я знал выделенное, то мог бы при старте приложения вызвать их методы Initialize() и подписаться на события. Собственно из-за чего вопрос. Есть интерфейс приложения. По нажатию кнопки генерируется некоторое событие. На это событие должны реагировать другие части интерфейса. Если они уже созданы, то все просто: при создании компонента я делаю подписку. Но если компонент еще не создан, например диалоговое окно которое должно быть создано только по событию, то к его классу обращений еще не было, не вызывалось ни одного его метода, т.е. вообще никак к этому классу никто не обращался, и соответственно некуда добавить подписку на событие. Чтобы класс себя подписал надо вызвать какой-то метод этого класса.

Да, на самом деле я знаю что это за класс, какое у него имя и в каком модуле он расположен. Я могу при запуске приложения прямо в main ветке вызвать его метод и осуществить подписку. Но при каких-либо изменениях я должен буду постоянно редактировать main. Этого хотелось бы избежать. Т.е. если диалоговое окно я решу убрать, то я просто удалю класс этого диалога, не трогая основной код. И точно также если я хочу добавить новый диалог, то я добавлю новый класс. То есть отключение и подключение отдельных компонентов программы не должно затрагивать код. Должен быть механизм, который пробежит по всем классам проекта при запуске и скажет всем запустить метод с некоторым предопределенным именем (Initialize в моем случае).

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



Офлайн

#4 Ноя. 6, 2010 03:02:05

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

В питоне есть такая возможность, как интроспекция. Другими словами, во время выполнения программы можно узнать, какие модули загружены, какие классы находятся в этих модулях, какие методы есть у этих классов и есть ли метод, который отвечает за регистрацию класса и вызвать его. Можно действовать так. А еще можно после описания класса вызывать некоторую функцию (или метод некоторого класса), которая регистрирует данный класс. Можно написать декоратор класса, который регистрирует этот класс и тогда перед каждым классом, который нужно зарегистрировать, достаточно написать, например, @register_event. Можно еще что-нибудь придумать.

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



Отредактировано (Ноя. 6, 2010 03:11:19)

Офлайн

#5 Ноя. 6, 2010 03:40:23

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Вызвать статические методы некоторых классов при запуске

Soteric, Daevaorn внятно написал: используйте метаклассы - и будет вам счастье.
Незачем изобретать велосипед - он и так прекрасно работает.



Офлайн

#6 Ноя. 6, 2010 05:51:00

pasaranax
От:
Зарегистрирован: 2009-06-13
Сообщения: 574
Репутация: +  0  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

А че-то типа этого проканает?

class C1(object):
@classmethod
def initialize(cls):
print "C1 initialized"

class C2(object):
@classmethod
def initialize(cls):
print "C2 initialized"

for c in locals().values():
if hasattr(c, 'initialize'):
c.initialize()



Офлайн

#7 Ноя. 6, 2010 17:35:05

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

Все усугубляется тем, что даже модуль с этим классом нигде не импортируется :( Получается, что этот файл вообще лежит себе отдельно и программа даже не знает ее это или не ее. В locals и globals такой класс не попадет и интроспекцией воспользоваться здесь нельзя.

Про мета-классы совсем не понял. Я почитал документацию. Мета-классы позволяют создавать классы налету, добавлять в них методы, поля и т.д. Все это хорошо, напоминает рефлексию в C#, но как может помочь непонятно. Можно пример?

В итоге все что известно: класс находится в одном из пакетов/модулей по каталогу “ниже” главного файла; у класса есть метод initialize(). Я пишу на Jython, может быть со стороны явы это как-то можно решить.



Офлайн

#8 Ноя. 6, 2010 20:17:38

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

Можно предложить такое решение - сканируете директории и импортиуруете все подряд внутрь сканирующей функции то что при импорте отзовется импортируете по настоящему …

Это явно не питоновский стиль гурзить все подряд. Мне кажется надо смотреть в сторону пакетов с их __init__.py где можно проделать всю нужную работу.

Приведенные примеры поразили сложностью. В в документации ясно сказано, код класса исполняется в тот момент когда класс первый раз встречен интерпретатором. Те вы можете делать все что только вам взбредет в голову в теле класса

import inspect
class Tx(object):
print "hello! I am class ",inspect.getframeinfo(inspect.currentframe()).function
hello I am class Tx



Отредактировано (Ноя. 6, 2010 20:32:15)

Офлайн

#9 Ноя. 8, 2010 06:38:36

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Вызвать статические методы некоторых классов при запуске

Тут, батенька, вы несколько загнули. Нельзя из class code block получить доступ к этому самому классу - его попросту еще не существует.

Поэтому:

1. Декоратор для класса.

@deco
class A(object):
pass
Просто и сердито.

2. Метакласс
class Meta(object):
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
# А вот здесь уже имеем полностью созданный класс, для которого был указан наш метакласс.

class Base(object):
__metaclass__ = Meta

class A(Base):
pass
Метакласс не забудешь - если был прописан, хоть и в базовом классе - вызовется.
Зато декоратор нагляднее. И понимают его быстрее - магии меньше.

3. Просто пишем в коде.
class A(object):
pass

register(A)
Самый тупой и некрасивый метод.

Теперь об инициализации. Код прийдется импортировать, явно или неявно. Лучше всего, конечно, в __init__.py

Soteric, раз уж вы хотите использовать для сравнения C#…

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

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



Офлайн

#10 Ноя. 8, 2010 18:55:07

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Вызвать статические методы некоторых классов при запуске

Я с вами Андрей согласен что в тот момент когда я произвожу действия класс еще не создан, но всеже я привел рабочий код, как вы можете легко проверить. Я исходил из того что человеку нужен ведь не сам класс а информация о том что он существует и предназначен для решения данной задачи. А для этого класс не нужен. Достаточно его имени. Это и показано в приведенном коде.

Этим примером я хотел подчеркнуть что в отличии от компилируемых языков - классы питона исполняемый код.

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



Отредактировано (Ноя. 8, 2010 19:24:56)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version