Вы можете использовать встроенную функцию vars
, чтобы получить атрибуты большинства экземпляров в виде словаря. Это позволяет вызывать вызываемые объекты с атрибутами, например, используя **
-unpacking, чтобы использовать их в качестве аргументов ключевого слова:
class Car:
def __init__(self, color=None, brand=None, model=None):
self.brand = brand
self.color = color
self.model = model
def print_car(self):
print(
"This is a {color} {brand} manufactured in {model}".format(
**vars(self) # get and unpack attributes to keyword arguments
))
Это не обычное использование в методах, хотя и имеет свое применение. Классы имеют много возможностей, которые конфликтуют с явным деструктурированием - наиболее важно создание подклассов и свойств , делающих атрибуты не строго определенными.
Однако классы, предназначенные исключительно для хранения определенного c набора атрибутов, могут быть безопасно разрушить. Например, классы данных напрямую поддерживают преобразование экземпляров в сопоставления и последовательности . Это позволяет деструктурировать атрибуты по имени или порядку.
Если деструктуризация требуется часто, ее можно автоматизировать с помощью декораторов. Простой декоратор для деструктуризации первого аргумента выглядит так:
def destruct(method):
"""Mark a method to destructure ``self`` into its arguments"""
@wraps(method)
def wrapper(self, **kwargs):
return method(**vars(self), **kwargs)
return wrapper
Его можно применять, как и другие декораторы методов, например classmethod
, непосредственно в определении class
. Затем метод принимает каждый атрибут в качестве отдельного аргумента вместо одного аргумента self
.
class Car:
def __init__(self, color=None, brand=None, model=None):
self.brand = brand
self.color = color
self.model = model
@destruct
def print_car(color, brand, model):
print(f"This is a {color} {brand} manufactured in {model}")
Car(color='red', brand='audi', model=2001).print_car()
# This is a red audi manufactured in 2001
Обратите внимание, что destruct
является демонстратором. Например, vars
не работает для классов, использующих __slots__
- при необходимости можно использовать некоторые запасные варианты или при проверке класса '__annotations__
. Кроме того, метод больше не поддерживает позиционные аргументы - проверка подписи или иная нормализация аргументов позволят это.