Содержание статьи

В Python каждый объект содержит набор атрибутов, которые определяют его состояние. Для анализа и отладки часто требуется получить полный список этих полей, включая как публичные, так и приватные атрибуты. Простейший способ – использовать встроенные функции vars() и __dict__, возвращающие словарь полей экземпляра.
Метод dir() позволяет вывести все имена, связанные с объектом, включая методы и свойства базовых классов. Для практических задач часто требуется фильтровать этот список, оставляя только поля данных. Это особенно важно при работе с наследованием, где атрибуты могут определяться как в родительских, так и в дочерних классах.
Примеры ниже покажут, как автоматически вывести имена и значения всех атрибутов объекта, с учётом их уровня доступа и принадлежности к классу или экземпляру. Такой подход облегчает отладку и анализ данных, особенно при сложных структурах с большим количеством полей.
Использование функции vars() для просмотра атрибутов объекта

Функция vars() возвращает словарь, содержащий все атрибуты переданного объекта вместе с их текущими значениями. Она подходит для быстрого анализа экземпляров классов и позволяет получать только данные, без методов и встроенных свойств.
Пример использования vars() на простом классе:
| Код | Результат |
|---|---|
class User:
def __init__(self, name, age):
self.name = name
self.age = age
user = User("Иван", 30)
print(vars(user))
|
{'name': 'Иван', 'age': 30}
|
Если объект не передан, vars() возвращает словарь локальных переменных в текущей области видимости, что позволяет использовать её для проверки динамически создаваемых атрибутов.
Для обновления или изменения значений полей через vars() можно работать напрямую с возвращаемым словарём:
| Код | Результат после изменения |
|---|---|
attributes = vars(user) attributes['age'] = 31 print(user.age) |
31 |
Использование vars() удобно при отладке и при генерации отчетов о состоянии объектов, особенно если количество полей велико и их структура заранее неизвестна.

Применение метода __dict__ для получения словаря полей класса

Метод __dict__ предоставляет доступ к внутреннему словарю объекта или класса, где хранятся все его атрибуты и значения. Для экземпляров классов __dict__ содержит поля, определённые внутри конструктора или присвоенные динамически.
Пример получения словаря полей через __dict__:
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
item = Product("Книга", 450)
print(item.__dict__)
Результат:

{'name': 'Книга', 'price': 450}
Для класса напрямую __dict__ показывает атрибуты класса, включая методы и переменные класса, что позволяет различать поля экземпляра и поля самого класса:
print(Product.__dict__)
Использование __dict__ удобно для перебора и изменения значений атрибутов в цикле:
for key, value in item.__dict__.items():
print(f"{key}: {value}")
Такой подход полезен при создании функций сериализации объектов, динамическом копировании атрибутов или генерации логов состояния объектов в Python.
Получение всех атрибутов класса через dir() и фильтрация методов

Функция dir() возвращает полный список имен, связанных с объектом или классом, включая поля, методы и встроенные свойства. Для выделения только атрибутов данных требуется фильтровать результат, исключая методы и специальные имена, начинающиеся и заканчивающиеся двойным подчеркиванием.
Пример применения dir() с фильтрацией методов:

class Employee:
company = "TechCorp"
def __init__(self, name, position):
self.name = name
self.position = position
def work(self):
pass
attrs = [attr for attr in dir(Employee) if not callable(getattr(Employee, attr)) and not attr.startswith('__')]
print(attrs)
Результат:
['company']
Для экземпляра класса можно получить поля объекта аналогичным образом, исключив методы экземпляра:
emp = Employee("Анна", "Разработчик")
fields = [attr for attr in dir(emp) if not callable(getattr(emp, attr)) and not attr.startswith('__')]
print(fields)
Результат:
['company', 'name', 'position']
Этот подход удобен для анализа структуры объектов с наследованием и динамически создаваемыми атрибутами, позволяя быстро идентифицировать только данные без лишних методов.
Пример различий:
class Car:
wheels = 4 # поле класса
def __init__(self, color):
self.color = color # поле экземпляра
car1 = Car("красный")
car2 = Car("синий")
print(car1.__dict__) # {'color': 'красный'}
print(car2.__dict__) # {'color': 'синий'}
print(Car.__dict__.get('wheels')) # 4
Из примера видно, что изменение поля класса отражается на всех экземплярах, если они не имеют одноимённого поля экземпляра:
Car.wheels = 6 print(car1.wheels) # 6 print(car2.wheels) # 6 car1.wheels = 8 # создаётся поле экземпляра print(car1.wheels) # 8 print(car2.wheels) # 6
В Python атрибуты могут иметь разные уровни доступа:
- Публичные – обычные поля, доступные извне.
- Защищённые – начинаются с одного подчеркивания _attr, рекомендуются для внутреннего использования.
- Приватные – начинаются с двух подчеркиваний __attr, Python применяет name mangling для предотвращения прямого доступа.
- Получаем все имена объекта через dir(obj).
- Отбираем имена, начинающиеся с _ или __.
Пример:
class Account:
def __init__(self, user, balance):
self._user = user # защищённый
self.__balance = balance # приватный
acc = Account("Пётр", 5000)
for attr in dir(acc):
if attr.startswith("_"):
print(f"{attr}: {getattr(acc, attr)}")
Результат показывает защищённые и приватные поля, включая приватное с name mangling:
- _user: Пётр
- _Account__balance: 5000
Такой подход позволяет безопасно получать внутренние данные объектов для отладки и анализа без изменения логики доступа.
Автоматический перебор и печать всех полей с их значениями

Для полного анализа объекта часто требуется перебрать все его атрибуты, включая публичные, защищённые и приватные, и вывести значения. Комбинация dir() и getattr() позволяет это сделать автоматически без ручного перечисления полей.
Пример перебора и печати всех атрибутов:
class Book:
category = "Фантастика" # поле класса
def __init__(self, title, author, price):
self.title = title # публичное
self._author = author # защищённое
self.__price = price # приватное
book = Book("Тёмная материя", "Блейк", 350)
for attr in dir(book):
if not callable(getattr(book, attr)) and not attr.startswith('__') or attr.startswith('_Book__'):
print(f"{attr}: {getattr(book, attr)}")
Результат позволяет увидеть все данные объекта:
- title: Тёмная материя
- _author: Блейк
- _Book__price: 350
- category: Фантастика
Такой метод полезен при генерации логов, отладке и сериализации объектов, особенно когда структура класса сложная или создаются динамические атрибуты.
Вопрос-ответ:
Как вывести все поля экземпляра класса в Python?
Для получения всех полей объекта можно использовать функцию vars() или атрибут __dict__. Они возвращают словарь, где ключи — имена атрибутов, а значения — соответствующие данные. Это позволяет быстро просмотреть все текущие значения полей экземпляра без перебора вручную.
Чем отличается вывод полей класса и полей экземпляра?
Поля класса определяются в теле класса и общие для всех объектов, тогда как поля экземпляра создаются внутри конструктора через self и уникальны для каждого объекта. Для полей экземпляра используют obj.__dict__, а для полей класса — ClassName.__dict__. Это различие помогает понимать, какие данные относятся к конкретному объекту, а какие — к классу в целом.
Можно ли получить приватные и защищённые атрибуты объекта?
Да. Для защищённых атрибутов, начинающихся с одного подчеркивания, доступ возможен напрямую. Для приватных атрибутов с двойным подчеркиванием Python использует name mangling, и они отображаются как _ClassName__attr. Их можно получить через getattr(obj, attr) после определения правильного имени.
Как отфильтровать методы при выводе всех атрибутов класса?
Функция dir() возвращает все имена, связанные с объектом, включая методы и свойства. Чтобы оставить только поля данных, используют проверку callable(getattr(obj, attr)) и исключают имена, начинающиеся с двойного подчеркивания. Такой фильтр позволяет получить чистый список атрибутов без методов и встроенных свойств.
Можно ли автоматически перебрать и вывести все поля с их значениями?
Да. С помощью цикла по списку атрибутов, полученных через dir() или __dict__, и функции getattr() можно выводить имена и значения всех полей, включая публичные, защищённые и приватные. Это полезно для отладки, создания логов и анализа объектов с большим количеством атрибутов.
