在Python开发中,我们经常会打开一个包或模块的源代码文件,只为了找到其中的__all__声明。__all__这个特殊的属性,被广泛认为是定义模块中公开接口的最佳方式。然而,我今天要告诉你一个小秘密:你其实不需要__all__。
是的,你没有听错。__all__在Python模块中的使用,其实是一种过度设计的产物。在某些情况下,这个声明会给开发者们带来不必要的麻烦和限制。
首先,让我们来回顾一下__all__的作用。它被用来限制通过from module import * 导入的内容,只包括模块中定义的公开名称。这样做的目的是为了防止潜在的命名冲突和模糊性。但是,这种限制性的导入方式其实并不常见,更常见的是显式导入特定的名称,比如from module import name1, name2。
那么问题来了,为什么我们还需要在每个模块中定义__all__,为了一种我们并不经常使用的导入方式呢?
实际上,使用__all__也可能导致一些困惑。假设你在一个模块中定义了一系列名称,并在__all__中指定了这些名称。然后,你想要在另一个模块中引用这些名称,但却忘记了将它们添加到__all__中。这样,就会导致一些名称无法被导入。而且,由于__all__是一个简单的列表,无法直接体现模块的结构和层次,这也会增加代码的复杂性。
幸运的是,Python已经提供了更好的解决方案。通过使用别名来引入模块,并使用点号操作符来访问其中的公开接口,可以避免__all__带来的问题。这种显式导入的方式不仅更加清晰明了,还可以使代码更具可读性和维护性。
此外,Python社区也普遍认同不使用__all__的做法。许多知名的开源项目,如Django和requests等,都没有在其模块中定义__all__。这也说明了__all__并不是必需的,而且在大型项目中很容易产生混乱。
总而言之,虽然__all__看起来很花哨并且吸引眼球,但实际上它并不是定义Python模块中公开接口的最佳方法。通过显式导入和使用点号操作符,我们可以更好地控制模块的命名空间,并提高代码的可读性和可维护性。所以,让我们告别__all__,迎接更优雅的Python编程方式吧!
原文参考链接:https://jamesturk.net/posts/you-dont-need-all/
了解更多有趣的事情:https://blog.ds3783.com/