【问题标题】:How to create a python decorator programatically如何以编程方式创建 python 装饰器
【发布时间】:2014-08-08 20:10:36
【问题描述】:

我正在编写一个创建/提供各种 Python 装饰器的应用程序。我希望这个应用程序本地化,包括装饰器的名称。装饰器最终会被其他将我的应用用作框架的开发人员使用(将我的应用视为测试框架)。

理想情况下,我希望能够根据本地化设置动态创建装饰器。

例如,如果选择的语言是英语,我希望我的装饰器命名为“apple”,如果是法语,我希望它命名为“pomme”。

在 Python 代码中,它可能看起来像:

@apple
def my_func():
    pass

@pomme
def my_func():
    pass

我最终希望能够灵活地添加更多语言,而无需修改或复制一堆代码。理想情况下,我只有一个装饰器函数可以根据设置处理“apple”或“pomme”。

实现这一目标的最佳方法是什么?

【问题讨论】:

  • 装饰器只是遵循特定协议的函数(它们将函数作为参数并返回一个函数)。由于 Python 具有 first-class functions,因此您可以简单地将它们分配给您喜欢的任何名称。如果您想以动态/编程方式执行此操作,您的包的 __init__.py 将是一个明显的位置。
  • 话虽如此,我建议不要这样做。在我个人看来,源代码,包括变量名、文档和文档字符串,应该是英文的。语言的其余部分是(关键字、语句等),将其与任何母语混合都会使其更难阅读。
  • 我同意,不要这样做。用英语编写代码(尽管如果您认为英语作为第二语言的人可能会使用该框架,我建议您翻译文档)。
  • 另外考虑一下,您必须为每种语言提供不同的示例代码,因为所有的函数、变量和关键字名称都会不同。
  • 感谢您的所有 cmets。 Lukas,您能否详细说明我的包裹中的__init__.py 是如何用于执行此操作的?

标签: python decorator python-decorators


【解决方案1】:

首先,不要这样做。这会给您带来许多问题,并使您和您的用户的生活更加艰难。无论如何,python 是非常动态的,所以你可以做到这一点。

像这样设置你的包:

yourpackage/
    __init__.py
    decorators.py

decorators.py:

# List all decorators you want to publish. Use english names here.
__all__ = ['apple', 'orange', ...]

# Here come implementations named in english
def apple(...):
    ...

...

__init__.py:

# Whatever over submodules export or just []
__all__ = [...]

from . import decorators

# Get locale somehow
LOCALE = ...

# This translation function could be as complex as you wish
# I use a lookup in hard-coded dict
TRANSLATIONS = {
    'fr': {'apple': u'pomme', ...},
    ...
}
def _translate_name(name):
    # If something is not translated we use default english name,
    # could be easily changed to raise error
    return TRANSLATIONS.get(LOCALE, {}).get(name, name)

# Generate dynamic attributes to current module and add them to __all__
import sys
this_module = sys.modules[__name__]

for name in decorators.__all__:
    translated = _translate_name(name)
    setattr(this_module, translated, getattr(decorators, name))
    __all__.append(translated)

__init__.py 中管理__all__ 是可选的。这是为了允许from yourmodule import *

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-24
    • 2011-04-13
    • 2016-03-08
    • 2019-08-31
    • 2017-11-16
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    相关资源
    最近更新 更多