За последнюю неделю я просмотрел некоторый код на Python в Stackstorm (размещенный на GitHub ), и благодаря этому я узнал несколько интересных новинок . Может быть, «новый» — не правильный термин, но эти вещи были новыми для меня, и я хотел поделиться ими с вами.
Код, на который я ссылаюсь, находится в нескольких местах Stackstorm, первый элемент :
@six.add_metaclass(abc.ABCMeta)
class Access(object):
Две вещи здесь:
1. six.add_metaclass — делает Access метаклассом таким образом, который совместим как с Python2, так и с Python3. В целом, шесть пакетов имеют целью помочь разработчикам перенести их код с Python 2 на Python 3, написав код, совместимый с обоими. Отсюда и название: шесть = 2 * 3. Чтобы узнать больше: https://pypi.python.org/pypi/six
2. abc.ABCMeta — а еще один пакет встроенного, его цель состоит в том, чтобы обеспечить поддержку A ВТОРЕФЕРАТ B азных C Девушек. Делая абстракцию класса, вы гарантируете, что никто не сможет создать из него объекты. Это полезно для (как минимум) трех целей:
а. Поддерживать логику, которая является общей для нескольких классов в одном месте
б. заставить пользователей реализовывать методы, аннотированные @ abc.abstractmethod (вы также можете заставить наследующие классы создавать определенные члены класса, используя аннотацию @ abc.abstractproperty ). Для получения дополнительной информации в отношении см. Документы .
с. создавая синглтон. Я до сих пор не убежден в полезности создания синглтона в Python (поскольку у нас есть модули), но, если вы захотите это сделать, вы можете либо создать метакласс и вызвать его методы как ClassName.method (), либо расширить метакласс но не реализовывать абстрактный метод или абстрактный свойства. Без реализации абстрактных методов / свойств наследующий класс также станет абстрактным. Этот метод используется в нескольких разных местах в StackStorm. Если вы хотите увидеть несколько примеров, ищите классы, наследуемые от Access .
3. Это заняло у меня некоторое время, чтобы обернуть голову (для этого требуется ум «функционального программирования»):
def decorate(f):
@functools.wraps(f)
def callfunction(*args, **kwargs):
Называя @ functools.wraps (е) мы используем декоратор внутри декоратора. Не тривиально …
Чтобы понять основную идею «functools.wraps», проще пройти через следующие пункты / процесс (по крайней мере, для меня проще…):
-
Когда вы декорируете функцию, вы создаете новую функцию, которая оборачивает «оригинальную» и возвращает обертку
-
Обертка используется для того, чтобы иметь возможность выполнять все виды задач до / после применения «исходной» функции. Примеры: подготовка аргументов для «исходной функции», определение времени выполнения функции, добавление журналов печати до и после и т. Д.
-
Скажем, у вас есть обернутая функция f, возвращенная из декоратора, затем пользователь увидит описание (метаданные) декоратора вместо f, исходной функции.
-
Чтобы избежать этой путаницы, на рисунке появляется @ functools.wraps (f) : аннотируя функцию-обертку с помощью @ functools.wraps (f) — вы убедитесь, что пользователь обертки увидит то же описание / метаданные как исходная функция. Под «описанием» я подразумеваю сигнатуру функции (имя функции и имена аргументов, которые она принимает).
Надеюсь, это полезно!