简体   繁体   English

如何以编程方式创建python装饰器

[英]How to create a python decorator programatically

I am writing an app that creates/provides various Python decorators. 我正在编写一个创建/提供各种Python装饰器的应用程序。 I'd like this app to be localized, including the names of the decorators. 我希望此应用程序可以本地化,包括装饰器的名称。 The decorators would ultimately be used by other developers who are using my app as a framework (think of my app as a test framework). 装饰器最终将由使用我的应用程序作为框架的其他开发人员使用(认为我的应用程序为测试框架)。

Ideally, I'd like to have the ability to create the decorators dynamically based on the localization settings. 理想情况下,我希望能够根据本地化设置动态创建装饰器。

For instance, if the language selected is English, I'd like my decorator to be named "apple", and if it's French, I'd like it to be named "pomme". 例如,如果选择的语言是英语,则我希望将其装饰器命名为“苹果”,如果是法语,则将其命名为“ pomme”。

In the Python code, it would either look like: 在Python代码中,它看起来像:

@apple
def my_func():
    pass

or 要么

@pomme
def my_func():
    pass

I ultimately want to have the flexibility to add many more languages without having to modify or duplicate a bunch of code. 我最终希望能够灵活地添加更多的语言,而不必修改或复制一堆代码。 Ideally, I would only have one decorator function that would handle "apple" or "pomme" depending on the settings. 理想情况下,我只有一个装饰器功能可以根据设置来处理“苹果”或“绒球”。

What's the best way to achieve this? 实现此目标的最佳方法是什么?

First, don't do this. 首先,不要这样做。 This will bring many problems upon you and make life much harder for you and your users. 这将给您带来许多问题,并使您和您的用户的生活更加艰难。 Anyway, python is very dynamic so you can do that. 无论如何,python非常动态,因此您可以做到这一点。

Setup your package like that: 像这样设置您的软件包:

yourpackage/
    __init__.py
    decorators.py

In 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(...):
    ...

...

In __init__.py : __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)

Managing __all__ in __init__.py is optional. __init__.py管理__all__是可选的。 This is to allow from yourmodule import * . 这是允许from yourmodule import *

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM