В Is it a good practice to add names to __all__ using a decorator?, Ed L предлагает следующее, которые должны быть включены в какой-то полезной библиотеке:
import sys
def export(f):
"""Use a decorator to avoid retyping function/class names.
* Based on an idea by Duncan Booth:
http://groups.google.com/group/comp.lang.python/msg/11cbb03e09611b8a
* Improved via a suggestion by Dave Angel:
http://groups.google.com/group/comp.lang.python/msg/3d400fb22d8a42e1
"""
mod = sys.modules[fn.__module__]
if hasattr(mod, '__all__'):
name, all_ = f.__name__, mod.__all__
if name not in __all__:
all_.append(name)
else:
mod.__all__ = [fn.__name__]
return f
Мы адаптированное имя в соответствии с другими примерами. При этом в местной библиотеке утилиты, вы бы просто написать
from .utility import export
, а затем начать использовать @export
. Только одна строка идиоматического Python, вы не можете получить намного проще, чем это. С другой стороны, модуль требует доступа к модулю, используя свойство __module__
и кеш sys.modules
, оба из которых могут быть проблематичными в некоторых более эзотерических установках (таких как специализированные механизмы импорта или функции обертывания от другого модуля до создавать функции в этом модуле).
The python partatpublicpackage от Barry Warsaw делает что-то похожее на это. Он также предлагает синтаксис на основе ключевых слов, но вариант декоратора основан на тех же шаблонах, которые были использованы выше.
This great answer от Aaron Hall предлагает что-то очень похожее, с еще двумя строками кода, поскольку он не использует __dict__.setdefault
. Может быть предпочтительнее, если по какой-то причине проблема с манипулированием модулем __dict__
.
Критика: '__dict__' семантически не является частью публичного API. Я бы предпочел избегать прямых изменений нижнего уровня в пользу абстракций более высокого уровня - даже на таком коде. Я считаю это немного более безопасным, хотя мне будет трудно думать о сценарии, в котором ваш код здесь не работает. Также спасибо за ссылку, ура! –
Поскольку это вики сообщества, я объединил логику, чтобы избежать использования '__dict__' напрямую. Если вы согласны, вы можете отметить указанные выше комментарии для удаления. Другие вещи, которые я улучшил, перемещают кредиты от docstring до конца вашего ответа и улучшают docstring, чтобы проиллюстрировать использование, чтобы, возможно, пройти доктрины. Я не заинтересован в написании собственного ответа на этот конкретный вопрос. –