Модуль inspect и самый частый код разработчика, который можно упростить до пары строк
Превратите сложные задачи в простые: узнайте, как модуль inspect помогает разработчикам отлаживать и лучше понимать чужой код, а также сокращать время, затрачиваемое на рутинные действия.
Начнем с описания самых простых и полезных функций модуля.
getmodule и getfile
getmodule и getfile позволяют получить имя модуля и файла, в которых определен импортированный объект:
import inspect from fastai.vision.all import * inspect.getmodule(L)
inspect.getfile(L)
function signature
Для получения описания параметров и значений по умолчанию исследуемой функции обратитесь к signature:
def f(a, b:list=[2]): pass sig = inspect.signature(f) for name, param in sig.parameters.items(): print(f"Parameter: {name}") print(f" Default: {param.default}") print(f" Annotation: {param.annotation}") print(f" Kind: {param.kind}") print()
frame
Пожалуй, самым полезным объектом модуля является фрейм/блок. Функция currentframe возвращает ссылку на текущий блок кода, у которого есть следующие важные атрибуты:
- f_locals - словарь локальных переменных
- f_globals - словарь глобальных переменных
- f_back - позволяет обратиться к фрейму на уровень выше
- f_code - объект кода, привязанный к фрейму, как правило, описывает функцию, в которой происходит выполнение блока. В свою очередь, имеет атрибут co_varnames, содержащий имена аргументов и локальных переменных;
Ниже демонстрируются эти свойства фреймов:
def f2(a=1): frame = inspect.currentframe() print(f'f2 local vars - {(frame.f_locals.items())}') print(f'f2 func vars and locals - {frame.f_code.co_varnames}') print(f'f1 func vars and locals - {frame.f_back.f_code.co_varnames}') print(f'f0 func vars and locals - {frame.f_back.f_back.f_code.co_varnames}') def f1(b): f2() def f0(c=2): f1(2) f0()
store_attr
Представленные выше свойства можно использовать для автоматизации присвоения внутренним атрибутам значений переменных, передаваемых в конструкторе класса, вида:
Этот шаблонный код, пожалуй, писал каждый питонист хотя бы раз.
class C(): def __init__(self, a, b): frame = inspect.currentframe() for k, v in frame.f_locals.items(): setattr(self, k, v) item = C(a=3, b=[1, 3]) item.a, item.b
Если делать то же через функцию, то понадобится обратиться к вышестоящему фрейму:
def copy_args(): frame = inspect.currentframe().f_back code = frame.f_code args = code.co_varnames self = frame.f_locals[args[0]] for k, v in frame.f_locals.items(): setattr(self, k, v) class C(): def __init__(self, a, b): copy_args() item = C(a=3, b=[1, 3]) item.a, item.b
Схожий функционал заложен в функции store_attr из модуля fastcore.basics:
from fastcore.basics import store_attr class C(): def __init__(self, a, b): store_attr() item = C(a=3, b=[1, 3]) item.a, item.b
stack
Еще посредством функции stack модуля inspect из произвольной строки можно получить информацию о стеке вызовов по аналогии с тем, который выводится при ошибке. Пусть у нас есть модуль:
После вызова f0 мы получим информацию о номере строки текущего фрейма (lineno), функции (function) и файле, в котором она находится (filename). Кроме того, ниже из стека выводится информация о служебных инструментах, которые используются collab-ом:
import sys sys.path.append('/content/drive/MyDrive/Colab Notebooks') from my_funcs.module import f0 f0()