Вызов метода класса по имени в python

Зайчатки разума

Записная книжка айтишника

Вызов метода класса по имени в python

2019-01-15 18:50:43 — Evgeniy Shumilov

  Недавно столкнулся с одной простой задачей, с которой раньше cталкиваться не приходилось, поэтому оставлю себе здесь запись в качестве памятки. В MicroPython необходимо было для одного класса написать встроенный менеджер задач - некий аналог cron и таймера, который бы позволил микроконтроллеру в общем цикле вызывать методы этого же класса (например, проверка состояния GPIO, датчиков, подключения к WiFi, MQTT и т.п.) по расписанию или через заданное количество времени после наступления какого-либо события. В числе прочего планировалась возможность фильтровать задачи по имени для динамической расстановки их приоритетов и я счёл, что лучшим вариантом в этом случае будет хранение в структуре данных имени метода, затем, возможно, создание словаря, ключами которого будут имена методов. Заодно и имя метода в виде строки куда проще передавать в другой метод в качестве параметра плюс аттрибуты отдельным кортежем во втором параметре. Использовать для обратного преобразования (да и для практически любых других задач) eval - мягко говоря, дурной тон, поэтому пришлось мучать гугл. Решение оказалось не простым, а очень простым. Я уже устал удивляться подобному при программировании на python, но всё ещё продолжаю это делать.


  Вот тестовый метод класса:

def getParam(self, param): 
if param:
return self.config.get(param)
else:
return None 

  Следующий пример показывает, как можно получить этот метод и использовать снаружи экземпляра класса по его имени:

from esmodule import ESModule
esm = ESModule()
# 2507 [debug]: Found config file, loading...
esm.getParam('essid')
# 'vedroid'
m = getattr(ESModule, 'getParam')
m
# <function getParam at 0x3fff0de0>
m(esm, 'essid')
# 'vedroid'

  Как видите, всё работает. Естественно, данный способ можно использовать и внутри самого класса, передавая вместо экземпляра класса self. Так же это должно работать в полноценных версиях Python, но я пока не проверял - не было необходимости. Если нужно получить глобальный метод по имени, это можно сделать ещё проще:

m = globals()['methodName']

P.S.: Может быть я просто не умею готовить python и передавать один метод в другой с параметрами, если у вас есть ссылка, куда вы бы хотели ткнуть меня носом - не стесняйтесь, я буду только благодарен. Я всё-таки не программист.

Теги: python

comments powered by Disqus