Inspect.getmembers: примеры (PYTHON)

Интроспекция объектов с помощью функции 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.

Расширенные примеры использования

Получение всех статических методов класса:

Пример python
import inspect

class Класс:
    @staticmethod
    def статик():
        return 'статический'
    
    def обычный(self):
        pass

результат = inspect.getmembers(Класс, predicate=inspect.isstaticmethod)
print(результат)
[('статик', <staticmethod object at 0x...>)]

Исследование модуля с фильтрацией по типу данных:

Пример python
import inspect, math

# Получение всех функций из модуля math
функции_модуля = inspect.getmembers(math, predicate=inspect.isfunction)
print([имя for имя, знач in функции_модуля[:3]])
['acos', 'acosh', 'asin']

Использование для отладки: вывод всех атрибутов объекта с их типами.

Пример python
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-объектами, но не являющихся методами (например, свойства или функции):

Пример python
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...>)]

питон inspect.getmembers function comments

En
Inspect.getmembers Return all members of an object as (name, value) pairs