← Назад к вопросам

Как посмотреть атрибуты объекта?

2.0 Middle🔥 171 комментариев
#Python Core#Soft Skills

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Просмотр атрибутов объекта в Python

Этот вопрос о интроспекции (introspection) — способности программы анализировать самой себя. Существует много способов посмотреть атрибуты объекта.

1. Функция dir() — самый простой способ

class Person:
    class_var = "я переменная класса"
    
    def __init__(self, name: str):
        self.name = name
        self._private = "приватное"
    
    def greet(self):
        return f"Hello, {self.name}"

person = Person("Alice")

# dir() показывает ВСЕ атрибуты и методы
attributes = dir(person)
print(attributes)
# [__class__, __delattr__, __dict__, __dir__, __doc__, __eq__,
#  __format__, __ge__, __getattribute__, __gt__, __hash__, __init__,
#  __init_subclass__, __le__, __lt__, __module__, __ne__, __new__,
#  __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__,
#  __str__, __subclass_hook__, __weakref__, _private, class_var,
#  greet, name]

2. __dict__ — словарь атрибутов экземпляра

person = Person("Alice")

# Показывает только атрибуты ЭКЗЕМПЛЯРА (не класса)
print(person.__dict__)
# {name: Alice, _private: приватное}

# Для класса:
print(Person.__dict__)
# {__module__: __main__, __doc__: None, class_var: ...,
#  __init__: <function>, greet: <function>, ...}

3. vars() — альтернатива __dict__

print(vars(person))   # То же самое что person.__dict__
# {name: Alice, _private: приватное}

print(vars(Person))   # То же самое что Person.__dict__

4. getattr() и hasattr() — проверка атрибутов

# Проверка наличия
if hasattr(person, "name"):
    print("У объекта есть атрибут name")

if hasattr(person, "nonexistent"):
    print("Не выведется")
else:
    print("Атрибута нет")

# Получение значения
name = getattr(person, "name")
print(name)  # Alice

# С дефолтом
age = getattr(person, "age", 25)
print(age)  # 25 (дефолт, потому что нет атрибута age)

5. setattr() и delattr() — изменение атрибутов

# Установка нового атрибута
setattr(person, "age", 30)
print(person.age)  # 30
print(person.__dict__)  # {name: Alice, _private: ..., age: 30}

# Удаление атрибута
delattr(person, "age")
print(hasattr(person, "age"))  # False

6. Различие между атрибутами

class Example:
    class_var = "класс"  # Атрибут класса
    
    def __init__(self):
        self.instance_var = "экземпляр"  # Атрибут экземпляра
    
    def method(self):
        local_var = "локальная"  # Локальная переменная (НЕ атрибут)
        return local_var

obj = Example()

# Атрибуты объекта
print(dir(obj))  # Включает class_var, instance_var, method и встроенные

# Только атрибуты ЭКЗЕМПЛЯРА
print(obj.__dict__)  # {instance_var: экземпляр}

# Только атрибуты КЛАССА
print(Example.__dict__.keys())  # dict_keys([__module__, __doc__,
                                #            class_var, __init__, method, ...])

# Поиск атрибута: сначала в экземпляре, потом в классе
print(obj.class_var)  # "класс" (найден в классе)
print(obj.instance_var)  # "экземпляр" (найден в экземпляре)

7. Фильтрация атрибутов

# Только пользовательские атрибуты (без магических __...__)
user_attrs = [attr for attr in dir(obj) if not attr.startswith("_")]
print(user_attrs)  # [class_var, greet, instance_var, name]

# Только методы
methods = [attr for attr in dir(obj) if callable(getattr(obj, attr))]
print(methods)  # [greet, count, index, ...]

# Только свойства (property)
properties = [attr for attr in dir(type(obj))
              if isinstance(getattr(type(obj), attr), property)]

# Только атрибуты, не начинающиеся с нижнего подчёркивания
public_attrs = {k: v for k, v in obj.__dict__.items()
                if not k.startswith("_")}
print(public_attrs)  # {name: Alice}

8. inspect модуль — для глубокого анализа

import inspect

class Calculator:
    def add(self, a: int, b: int) -> int:
        """Сложение двух чисел."""
        return a + b
    
    def multiply(self, a: int, b: int) -> int:
        """Умножение двух чисел."""
        return a * b

calc = Calculator()

# Получить сигнатуру метода
sig = inspect.signature(calc.add)
print(sig)  # (a: int, b: int) -> int
print(sig.parameters)  # OrderedDict([(a, <Parameter>), (b, <Parameter>)])

# Получить параметры
for param_name, param in sig.parameters.items():
    print(f"{param_name}: {param.annotation}")
# a: <class int>
# b: <class int>

# Получить docstring
print(inspect.getdoc(calc.add))  # "Сложение двух чисел."

# Все методы класса
members = inspect.getmembers(calc, predicate=inspect.ismethod)
for name, method in members:
    print(f"{name}: {method}")

# Исходный код метода
print(inspect.getsource(calc.add))
# def add(self, a: int, b: int) -> int:
#     """Сложение двух чисел."""
#     return a + b

# Информация о классе
print(inspect.getmembers(Calculator, predicate=inspect.isfunction))

9. type() — получить тип объекта

person = Person("Alice")

# Тип объекта
print(type(person))  # <class __main__.Person>
print(type(person).__name__)  # Person

# MRO — Method Resolution Order (порядок поиска методов)
print(type(person).__mro__)  # (<class Person>, <class object>)

# Базовые классы
print(type(person).__bases__)  # (<class object>,)

10. __class__ и __mro__ для наследования

class Animal:
    pass

class Dog(Animal):
    pass

dog = Dog()

# Класс объекта
print(dog.__class__)  # <class __main__.Dog>
print(dog.__class__.__name__)  # Dog

# MRO — порядок поиска методов
print(Dog.__mro__)  # (<class Dog>, <class Animal>, <class object>)

# Проверка типа
print(isinstance(dog, Dog))  # True
print(isinstance(dog, Animal))  # True
print(isinstance(dog, object))  # True

11. Встроенные атрибуты (dunder)

class MyClass:
    def __init__(self):
        self.x = 1
    
    def __repr__(self):
        return f"MyClass(x={self.x})"
    
    def __str__(self):
        return f"My object with x={self.x}"

obj = MyClass()

# Магические методы
print(obj.__class__)       # <class __main__.MyClass>
print(obj.__dict__)        # {x: 1}
print(obj.__module__)      # __main__
print(obj.__doc__)         # None или docstring класса
print(obj.__repr__())      # MyClass(x=1)
print(obj.__str__())       # My object with x=1
print(obj.__sizeof__())    # Размер в памяти

12. Полный пример интроспекции

import inspect

class DataClass:
    class_var = "Я переменная класса"
    
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
        self._private = "Приватное"
    
    def public_method(self):
        """Публичный метод."""
        return f"Hello, {self.name}"
    
    def _private_method(self):
        return "Приватный метод"
    
    @property
    def info(self):
        """Property для получения информации."""
        return f"{self.name} ({self.age})"

obj = DataClass("Alice", 30)

def introspect(obj):
    """Полная интроспекция объекта."""
    print("=== АТРИБУТЫ ===")
    print(f"__dict__: {obj.__dict__}")
    
    print("\n=== МЕТОДЫ ===")
    for name in dir(obj):
        if not name.startswith("_"):
            attr = getattr(obj, name)
            if callable(attr):
                print(f"  {name}(): {inspect.getdoc(attr)}")
    
    print("\n=== PROPERTIES ===")
    for name in dir(type(obj)):
        if not name.startswith("_"):
            attr = getattr(type(obj), name)
            if isinstance(attr, property):
                print(f"  {name} (property)")
    
    print("\n=== КЛАССОВЫЕ ПЕРЕМЕННЫЕ ===")
    for name, value in type(obj).__dict__.items():
        if not name.startswith("_") and not callable(value) and not isinstance(value, property):
            print(f"  {name}: {value}")
    
    print("\n=== ИЕРАРХИЯ ===")
    print(f"  Type: {type(obj)}")
    print(f"  MRO: {type(obj).__mro__}")

introspect(obj)

Сравнение методов

ФункцияЧто показываетПримечание
dir()ВСЕ атрибуты и методыВключает магические методы
__dict__Атрибуты экземпляраНе включает атрибуты класса
vars()Альтернатива __dict__То же самое
getattr()Получить значениеС дефолтом
hasattr()Проверить наличиеДля проверки
inspectГлубокий анализСигнатуры, исходный код
type()Тип объектаДля определения класса
isinstance()Проверка типаС учётом наследования

Лучшие практики

✅ Для просмотра атрибутов:

  • dir() — быстрая проверка
  • vars() — атрибуты экземпляра
  • inspect — серьёзный анализ
  • getattr() — безопасное получение

❌ Избегай:

  • Полагаться на __dict__ для всех атрибутов (свойства и методы не включены)
  • Прямого обращения к __ атрибутам (они могут измениться)
  • Модификации __dict__ вручную (используй setattr)

Интроспекция — мощный инструмент для отладки, тестирования и создания универсального кода.

Как посмотреть атрибуты объекта? | PrepBro