使用装饰器向__all__添加名称是一个好习惯吗?

Ed *_*d L 20 python coding-style

这是Python中的一个好习惯(来自Active State Recipes - Public Decorator)吗?

import sys

def public(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
  """
  all = sys.modules[f.__module__].__dict__.setdefault('__all__', [])
  if f.__name__ not in all:  # Prevent duplicates if run from an IDE.
      all.append(f.__name__)
  return f

public(public)  # Emulate decorating ourself
Run Code Online (Sandbox Code Playgroud)

一般的想法是定义一个装饰器,它接受一个函数或类,并将其名称添加到__all__当前模块的名称.

lui*_*dro 17

在Python中执行此操作的更惯用的方法是通过使用下划线开始使用其名称将私有函数标记为私有:

def public(x):
      ...


def _private_helper(y):
    ...
Run Code Online (Sandbox Code Playgroud)

更多人会熟悉这种风格(语言也支持:_private_helper即使你不使用也不会导出__all__),而不是你的public装饰者.

  • @EdL那是因为如果你一直使用下划线表示"私人"的东西而不是公共事物的下划线,你根本就不需要`__all__` (4认同)
  • @TobiasKienzler @NeilG [标准库的部分](https://hg.python.org/cpython/file/3.5/Lib/collections/__init__.py)使用模式`import module as _module`,所以我想称之为相当成熟的做法. (3认同)
  • 这似乎没有解决装饰器解决的问题:保持`__all__`中的名称是最新的. (2认同)
  • @NeilG既不建议使用@public装饰器,_common_实践正在按预期使用`__all__` (2认同)

Ste*_*ski 6

是的,这是一个很好的做法.这个装饰器允许您在功能或类定义中陈述您的意图,而不是直接在之后.这使您的代码更具可读性.

@public 
def foo():
    pass 

@public 
class bar():
    pass

class helper(): # not part of the modules public interface! 
    pass
Run Code Online (Sandbox Code Playgroud)

注意: helper模块的用户仍然可以访问modulename.helper.它只是没有导入from modulename import *.

  • 我不一定会说这是一个很好的做法.在模块开头明确定义`__all__`的优点是,任何人(可能是你)查看它都可以很容易地确定通过`import*`导出的内容以及模块的公共API的一部分.使用公共装饰器使这变得更加困难.但是,如果你使用装饰器,你可以在看模块的一个成员时判断它是否在`__all__`中.所以两者各有利弊. (7认同)