2011-06-01 23 views
20

这是Python中的一个很好的练习(从Active State Recipes -- Public Decorator)?使用装饰器向__all__添加名称是一种好的做法吗?

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 

总的想法是定义一个装饰,需要一个功能或 类,并增加了它的名字到当前模块的__all__

+2

修正了标题,正如有些人指出的那样 – 2011-06-01 18:57:42

+0

虽然这看起来不错,但我发现它混淆了我的IDE(PyCharm 2016.1.4),它大部分都会破坏目的。如果有足够的IDE支持,我会使用它。 – 2016-07-13 20:22:25

+0

获得这个装饰器100%防弹似乎更难:看到[Python bug#26632](https://bugs.python.org/issue26632)和['atpublic'模块](https:// pypi。 python.org/pypi/atpublic)在那里提到。 – kostix 2016-12-10 09:25:29

回答

6

是的,这是一个很好的做法。这个装饰器允许你在函数或类定义中表达你的意图,而不是直接在之后。这使您的代码更具可读性。

@public 
def foo(): 
    pass 

@public 
class bar(): 
    pass 

class helper(): # not part of the modules public interface! 
    pass 

注:helper仍然是由modulename.helper一个模块的用户访问。它只是没有与from modulename import *进口。

+7

我不一定会说这是一个很好的做法。在模块开头明确定义'__all__'的好处是,任何人(可能你)都可以很容易地通过'import *'确定输出的内容,模块的公共API是什么。使用公共装饰器使得这变得更加困难。但是,如果您使用装饰器,则可以在查看模块的成员时判断它是否在'__all__'中。所以两者各有利弊。 – darkfeline 2013-03-19 23:58:37

+0

Everything darkfeline said plus - 它使用朴素代码标记器打破IDE的智能感知/代码完成。 – synthesizerpatel 2013-11-30 05:06:04

1

这不会自动将名称添加到__all__,它只是允许您通过用@public装饰它来为所有人添加功能。对我来说似乎是一个不错的主意。

+0

通过自动,我基本上意味着不用在列表中明确输入名称 – 2011-06-01 18:57:10

+1

是的。 (另外11个字符) – LaC 2011-06-01 19:18:19

1

我认为这个问题有点主观,但我喜欢这个主意。我通常在我的模块中使用__all__,但我有时会忘记添加一个新功能,我打算将其作为模块公共接口的一部分。由于我通常通过名称而不是通配符导入模块,因此直到我的团队中的其他人(使用通配符语法导入模块的整个公共接口)开始抱怨为止,我才注意到错误。

注意:问题的标题是误导的,因为其他人已经注意到了答案。

17

更习惯的方法在Python做,这是通过用下划线开始他们的名字,以纪念私有函数私有:

def public(x): 
     ... 


def _private_helper(y): 
    ... 

更多的人会熟悉这种风格(也由支持语言:_private_helper即使不使用__all__也不会被导出),而不是使用您的public修饰器。

+2

这似乎没有解决装饰者解决的问题:将__all__中的名称保持为最新。 – 2011-06-01 20:18:10

+4

@EdL这是因为如果你一直使用下划线作为“私人”事物并且没有公共事物的下划线,那么你根本不需要'__all__' – 2013-05-15 08:02:53

+1

@TobiasKienzler是不是将任何导入的模块导出?你可能仍然想阻止这些。 – 2015-10-23 08:08:16

相关问题