管理 __all__ 的导出装饰器 [英] Export decorator that manages __all__

查看:22
本文介绍了管理 __all__ 的导出装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

适当的 Python 模块将在 一个名为 __all__公共符号代码>.管理该列表可能很乏味,因为您必须将每个符号列出两次.当然有更好的方法,可能是使用装饰器,所以人们只需将导出的符号注释为 @export.

A proper Python module will list all its public symbols in a list called __all__. Managing that list can be tedious, since you'll have to list each symbol twice. Surely there are better ways, probably using decorators so one would merely annotate the exported symbols as @export.

你会如何编写这样的装饰器?我确信有不同的方法,所以我希望看到几个答案,其中包含足够的信息,以便用户可以将这些方法相互比较.

How would you write such a decorator? I'm certain there are different ways, so I'd like to see several answers with enough information that users can compare the approaches against one another.

推荐答案

使用装饰器?Ed L 建议将以下内容包含在某些实用程序库中:

In Is it a good practice to add names to __all__ using a decorator?, Ed L suggests the following, to be included in some utility library:

import sys

def export(fn):
    """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 = fn.__name__
        all_ = mod.__all__
        if name not in all_:
            all_.append(name)
    else:
        mod.__all__ = [fn.__name__]
    return fn

我们修改了名称以匹配其他示例.在本地实用程序库中使用它,您只需编写

We've adapted the name to match the other examples. With this in a local utility library, you'd simply write

from .utility import export

然后开始使用@export.只需一行惯用的 Python,就没有比这更简单的了.不利的一面是,该模块确实需要通过使用 __module__ 属性和 sys.modules 缓存来访问该模块,这两者都可能在一些更深奥的设置中存在问题(例如自定义导入机制,或包装来自另一个模块的函数以在该模块中创建函数).

and then start using @export. Just one line of idiomatic Python, you can't get much simpler than this. On the downside, the module does require access to the module by using the __module__ property and the sys.modules cache, both of which may be problematic in some of the more esoteric setups (like custom import machinery, or wrapping functions from another module to create functions in this module).

python 部分 atpublic package by Barry Warsaw 做了类似的事情.它也提供了一些基于关键字的语法,但装饰器变体依赖于上面使用的相同模式.

The python part of the atpublic package by Barry Warsaw does something similar to this. It offers some keyword-based syntax, too, but the decorator variant relies on the same patterns used above.

这个很棒的答案 Aaron Hall 提出了一些非常相似的建议,另外还有两行代码,因为它不使用 __dict__.setdefault.如果由于某种原因操作模块 __dict__ 有问题,则可能更可取.

This great answer by Aaron Hall suggests something very similar, with two more lines of code as it doesn't use __dict__.setdefault. It might be preferable if manipulating the module __dict__ is problematic for some reason.

这篇关于管理 __all__ 的导出装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆