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

Как получить список атрибутов объекта в Python?

1.0 Junior🔥 121 комментариев
#Python Core

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

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

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

Получение списка атрибутов объекта в Python

Python предоставляет несколько способов интроспекции для получения информации об атрибутах объекта. Выбор зависит от конкретного использования.

1. dir() — наиболее распространённый способ

class Person:
    class_attr = 'class attribute'
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def greet(self):
        return f'Hello, {self.name}'

person = Person('Alice', 30)

# Получить все атрибуты (включая методы и dunder attributes)
all_attrs = dir(person)
print(all_attrs)
# ['__class__', '__delattr__', '__doc__', ..., 'age', 'class_attr', 'greet', 'name']

# Отфильтровать только пользовательские атрибуты (без dunder)
user_attrs = [attr for attr in dir(person) if not attr.startswith('_')]
print(user_attrs)  # ['age', 'class_attr', 'greet', 'name']

2. dict — только атрибуты экземпляра

person = Person('Alice', 30)

# Получить словарь атрибутов экземпляра
print(person.__dict__)  # {'name': 'Alice', 'age': 30}
print(Person.__dict__)  # Словарь класса с методами

# Получить ключи (имена атрибутов)
attribute_names = list(person.__dict__.keys())
print(attribute_names)  # ['name', 'age']

3. vars() — удобная обёртка для dict

person = Person('Alice', 30)

# vars() возвращает __dict__
print(vars(person))  # {'name': 'Alice', 'age': 30}

# Эквивалентно
print(person.__dict__)  # Одно и то же

# vars() работает и на классах
print(vars(Person))  # Большой словарь с методами и атрибутами класса

4. getattr() — получить конкретный атрибут

person = Person('Alice', 30)

# Получить атрибут с дефолтным значением
name = getattr(person, 'name')           # 'Alice'
city = getattr(person, 'city', 'Moscow') # 'Moscow' (не существует, используется дефолт)

# Без дефолта — выбросит AttributeError
try:
    city = getattr(person, 'city')
except AttributeError:
    print('Атрибут не существует')

5. hasattr() — проверка наличия атрибута

person = Person('Alice', 30)

if hasattr(person, 'name'):
    print(person.name)  # Alice

if hasattr(person, 'city'):
    print(person.city)  # Не выполнится
else:
    print('Нет атрибута city')

# Получить только существующие атрибуты
existing_attrs = [attr for attr in dir(person) if hasattr(person, attr)]

6. inspect модуль — для детальной информации

import inspect

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def greet(self):
        return f'Hello, {self.name}'
    
    @property
    def is_adult(self):
        return self.age >= 18

person = Person('Alice', 30)

# Получить все члены (attributes + methods)
members = inspect.getmembers(person)
for name, value in members:
    if not name.startswith('_'):
        print(f"{name}: {type(value).__name__}")

# Вывод:
# age: int
# greet: method
# is_adult: bool (property)
# name: str

# Разделить на разные типы
print("\nAttributes:")
for name, value in inspect.getmembers(person):
    if not callable(value) and not name.startswith('_'):
        print(f"{name}: {value}")

print("\nMethods:")
for name, value in inspect.getmembers(person):
    if callable(value) and not name.startswith('_'):
        print(f"{name}")

print("\nProperties:")
for name, value in inspect.getmembers(Person):
    if isinstance(value, property):
        print(f"{name}")

7. Типизированные атрибуты (для dataclass и TypedDict)

from dataclasses import dataclass, fields
from typing import TypedDict

@dataclass
class PersonData:
    name: str
    age: int
    email: str = 'unknown'

# Получить информацию о полях dataclass
for field in fields(PersonData):
    print(f"{field.name}: {field.type}")

# Вывод:
# name: <class 'str'>
# age: <class 'int'>
# email: <class 'str'>

# Для TypedDict
class PersonDict(TypedDict):
    name: str
    age: int

# Получить аннотации типов
print(PersonDict.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>}

8. annotations — для получения типов

class Person:
    name: str
    age: int
    
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

# Получить аннотации типов класса
print(Person.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>}

# Для функций
def greet(name: str, age: int) -> str:
    return f'Hello {name}'

print(greet.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}

9. Практический пример: Классификация атрибутов

import inspect

class AttributeAnalyzer:
    @staticmethod
    def analyze(obj):
        """Детально проанализировать все атрибуты объекта"""
        result = {
            'instance_attributes': {},
            'class_attributes': {},
            'methods': {},
            'properties': {},
        }
        
        # Атрибуты экземпляра
        if hasattr(obj, '__dict__'):
            result['instance_attributes'] = dict(obj.__dict__)
        
        # Через inspect
        for name, value in inspect.getmembers(obj):
            if name.startswith('_'):
                continue
            
            if isinstance(value, property):
                result['properties'][name] = str(value)
            elif callable(value):
                result['methods'][name] = inspect.signature(value)
            elif not isinstance(value, (type, type(obj.__class__))):
                # Атрибут класса
                result['class_attributes'][name] = value
        
        return result

class Person:
    class_var = 'class attribute'
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def greet(self):
        return f'Hi, {self.name}'
    
    @property
    def is_adult(self):
        return self.age >= 18

person = Person('Alice', 30)
analysis = AttributeAnalyzer.analyze(person)

print("Instance Attributes:", analysis['instance_attributes'])
print("Class Attributes:", analysis['class_attributes'])
print("Methods:", analysis['methods'].keys())
print("Properties:", analysis['properties'].keys())

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

МетодВозвращаетВключает dunderВключает методыСкорость
dir()СписокДаДаМедленнее
dictСловарьНетНет (только instance)Быстро
vars()СловарьНетНетБыстро
inspect.getmembers()Список кортежейДаДаМедленнее
getattr()Одно значение--Очень быстро
annotationsСловарь типовНетНетБыстро

11. Best Practices

# ✅ Для быстрого доступа к атрибутам экземпляра
instance_attrs = vars(obj)  # или obj.__dict__

# ✅ Для получения всех, включая методы
all_attrs = dir(obj)

# ✅ Для информации о типах
attributes_with_types = inspect.getmembers(obj)

# ✅ Для динамического доступа
value = getattr(obj, 'attribute_name', default_value)

# ✅ Для типизированного кода
from dataclasses import fields
field_names = [f.name for f in fields(MyDataClass)]

# ❌ Избегать
del obj.__dict__['attr']  # Прямое редактирование — плохая практика

# ✅ Вместо этого
delattr(obj, 'attr')

12. Экспортировать в JSON

import json

def object_to_dict(obj):
    """Сериализовать объект в словарь"""
    if hasattr(obj, '__dict__'):
        return obj.__dict__
    elif hasattr(obj, '__iter__'):
        return list(obj)
    else:
        return str(obj)

person = Person('Alice', 30)
person_dict = object_to_dict(person)
json_str = json.dumps(person_dict, indent=2)
print(json_str)

# Вывод:
# {
#   "name": "Alice",
#   "age": 30
# }

Выбирай метод в зависимости от задачи: dir() для общего списка, dict для быстрого доступа, inspect для детальной информации.