Я не люблю декораторы и метаклассы. Почти любое использование декоратора и любое использование метакласса ухудшает читаемость кода. Их трудно использовать без усложнения кода. Они приводят к трудновыявляемым багам. Так что их использование должно быть обосновано. И их не нужно использовать там, где можно легко и безболезненно обойтись без них.

Если сравнить использование остальных конструкций языка с использованием рогатки, то использование декоратора — это стрельба из пушки, а метаклассы — из системы залпового огня «Град». Последствия их неправильного использования влияют на кодовую базу примерно так же. Декоратор «разламывает» несколько функций и методов, метакласс «разрывает в клочья» несколько классов.

Так как их использовать правильно? И какие основные ошибки?

Метаклассы — очень тонкая материя. Для них я не возьмусь давать общие советы. Разве что только один: прежде чем использовать метаклассы, попробуйте решить проблему без них; если не получилось, попробуйте ещё раз; и только после этого используйте метаклассы. Ну и перед тем, как приступить, сообщите об этом решении остальным членам команды: «Ребята, для этой задачи я вынужден использовать метаклассы».

С декораторами проще. Я стараюсь следовать двум правилам:

  1. Не меняйте интерфейс функции. Будьте людьми: не добавляйте и не убавляйте количество параметров, не меняйте их названия и порядок. Если так нужно сделать, то декоратор — плохая идея. Для обычной функции лучше использовать functools.partial, для метода — написать в классе ещё один метод с нужным интерфейсом.
  2. Не превращайте функцию в класс или класс в функцию. Кроме редких случаев, делать это — плохая идея. Если уж надо обернуть функцию в класс декоратором, то переопределите у него __call__.

И напоследок. Старайтесь делать всё проще. Читаемость кода — один из важнейших показателей его качества. Сложные конструкции хороши на собеседовании. В продакшене исповедуйте принцип разумного консерватизма.