Модуль 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Можно часть параметров сохранить через store_attr, перечислив их в скобках через запятую, а часть определить самим:
from fastcore.basics import store_attr
class C():
def __init__(self, a, b, c):
store_attr('a, c')
self.b = a+c
item = C(a=3, b=3, c=5)
item.a, item.b, item.cstack
Еще посредством функции stack модуля inspect из произвольной строки можно получить информацию о стеке вызовов по аналогии с тем, который выводится при ошибке. Пусть у нас есть модуль:
После вызова f0 мы получим информацию о номере строки текущего фрейма (lineno), функции (function) и файле, в котором она находится (filename). Кроме того, ниже из стека выводится информация о служебных инструментах, которые используются collab-ом:
import sys
sys.path.append('/content/drive/MyDrive/Colab Notebooks')
from my_funcs.module import f0
f0()