Inspect.getmembers: примеры (PYTHON)
inspect.getmembers(object: object, predicate: callable = None): listОписание функции inspect.getmembers
Функция inspect.getmembers является частью модуля inspect в Python и служит для получения списка всех атрибутов и методов объекта. Она применяется в ситуациях, требующих интроспекции кода: при отладке, создании инструментов анализа, динамическом исследовании классов и модулей.
Функция возвращает список кортежей, где каждый кортеж содержит имя атрибута и его значение. Возвращаемые элементы сортируются по алфавиту по имени.
Аргументы функции:
- object (обязательный): Объект, члены которого необходимо получить. Это может быть модуль, класс, экземпляр, функция или любой другой объект Python.
- predicate (опциональный): Функция-предикат, принимающая один аргумент (значение атрибута) и возвращающая
TrueилиFalse. Если предикат указан, в результат включаются только те атрибуты, для которых предикат вернулTrue. Может бытьNone(по умолчанию), что означает отсутствие фильтрации.
Возвращаемое значение: список кортежей вида (имя_атрибута, значение_атрибута).
Примеры использования inspect.getmembers
Пример с простым объектом без фильтрации:
import inspect
class ПримерКласса:
а = 1
def метод(self):
pass
obj = ПримерКласса()
результат = inspect.getmembers(obj)
print(результат[:4])[('__class__', <class '__main__.ПримерКласса'>), ('__delattr__', <method-wrapper '__delattr__' of ПримерКласса object at 0x...>), ('__dict__', {}), ('__dir__', <built-in method __dir__ of ПримерКласса object at 0x...>)]Использование предиката для фильтрации только методов:
import inspect
class ПримерКласса:
а = 1
def метод(self):
pass
obj = ПримерКласса()
результат = inspect.getmembers(obj, predicate=inspect.ismethod)
print(результат)[('метод', <bound method ПримерКласса.метод of <__main__.ПримерКласса object at 0x...>>)]Фильтрация с помощью пользовательской функции:
import inspect
class ПримерКласса:
а = 1
б = 'строка'
def метод(self):
pass
obj = ПримерКласса()
результат = inspect.getmembers(obj, predicate=lambda x: isinstance(x, int))
print(результат)[('а', 1)]Похожие функции в Python
Для интроспекции объектов также применяются другие инструменты.
- dir(object): Возвращает отсортированный список строк с именами атрибутов объекта. Не возвращает значения. Используется для быстрого просмотра доступных атрибутов.
- vars(object): Возвращает словарь
__dict__объекта. Работает только для объектов, имеющих атрибут__dict__.inspect.getmembersпредоставляет более универсальный доступ. - inspect.getmro(cls): Возвращает кортеж классов, соответствующих порядку разрешения методов для класса
cls. Специализированная функция для работы с иерархией наследования. - object.__dict__: Прямой доступ к пространству имен объекта. Менее удобен, чем
getmembers, так как не обрабатывает случаи, когда атрибут отсутствует в__dict__.
Функцию inspect.getmembers предпочтительнее использовать, когда необходим полный список атрибутов со значениями, особенно с возможностью гибкой фильтрации.
Альтернативы в других языках программирования
Разные языки предоставляют свои механизмы рефлексии.
JavaScript: Используется Object.getOwnPropertyNames() или Reflect.ownKeys().
const obj = { a: 1, [Symbol('b')]: 2 };
console.log(Object.getOwnPropertyNames(obj));
console.log(Reflect.ownKeys(obj));['a'] ['a', Symbol(b)]
Java: Применяется Class.getMethods() или Class.getFields().
import java.lang.reflect.*;
public class Main {
public static void main(String[] args) {
Method[] methods = String.class.getMethods();
System.out.println(methods[0].getName());
}
}equals
PHP: Функция get_class_methods() для методов и get_class_vars() для свойств.
class Пример { public $a = 1; public function метод() {} }
print_r(get_class_methods('Пример'));
print_r(get_class_vars('Пример'));Array
(
[0] => метод
)
Array
(
[a] => 1
)C#: Используется Type.GetMembers().
using System;
using System.Reflection;
class Program {
static void Main() {
MemberInfo[] members = typeof(String).GetMembers();
Console.WriteLine(members[0].Name);
}
}Equals
В отличие от Python, эти функции часто возвращают только имена или метаинформацию, а не значения атрибутов экземпляра.
Типичные ошибки при использовании
Ошибка при передаче встроенного типа без атрибутов __dict__ с фильтрацией по несуществующему атрибуту.
import inspect
результат = inspect.getmembers(10, predicate=lambda x: x > 5)
print(результат)[]
Результат пуст, так как у целого числа нет атрибутов, которые можно проверить предикатом. Функция не вызывает ошибку, но возвращает пустой список.
Путаница между фильтрацией по имени и значению атрибута. Предикат получает значение атрибута, а не его имя.
import inspect
class Пример:
скрытый = 'значение'
видимый = 42
obj = Пример()
# Попытка фильтрации по имени атрибута (ошибочно)
результат = inspect.getmembers(obj, predicate=lambda val: 'скрытый' in str(val))
print(результат)[('скрытый', 'значение'), ('видимый', 42)]Предикат проверяет наличие подстроки 'скрытый' в строковом представлении значения, а не в имени атрибута.
Изменения в последних версиях Python
В Python 3.11 в функцию inspect.getmembers не вносились существенные изменения. Поведение и сигнатура функции остаются стабильными на протяжении многих версий. Основные обновления модуля inspect в последних версиях касались добавления новых функций для интроспекции, таких как inspect.getcoroutinestate.
Расширенные примеры использования
Получение всех статических методов класса:
import inspect
class Класс:
@staticmethod
def статик():
return 'статический'
def обычный(self):
pass
результат = inspect.getmembers(Класс, predicate=inspect.isstaticmethod)
print(результат)[('статик', <staticmethod object at 0x...>)]Исследование модуля с фильтрацией по типу данных:
import inspect, math
# Получение всех функций из модуля math
функции_модуля = inspect.getmembers(math, predicate=inspect.isfunction)
print([имя for имя, знач in функции_модуля[:3]])['acos', 'acosh', 'asin']
Использование для отладки: вывод всех атрибутов объекта с их типами.
import inspect
class СложныйОбъект:
def __init__(self):
self.число = 5
self.список = [1, 2]
self.словарь = {'a': 1}
obj = СложныйОбъект()
for имя, значение in inspect.getmembers(obj):
if not имя.startswith('__'):
print(f'{имя}: {значение} (тип: {type(значение).__name__}')словарь: {'a': 1} (тип: dict)
список: [1, 2] (тип: list)
число: 5 (тип: int)Фильтрация атрибутов, являющихся callable-объектами, но не являющихся методами (например, свойства или функции):
import inspect
class Класс:
@property
def свойство(self):
return 42
def метод(self):
pass
obj = Класс()
результат = inspect.getmembers(obj, predicate=lambda x: callable(x) and not inspect.ismethod(x))
print(результат)[('свойство', <property object at 0x...>)]