可以重复使用 Python 的内置函数的名称吗?

Is it OK to re-use the names of Python's built-in functions?

正如目前在 this question 中讨论的那样,我正在编写内置 rangexrange 函数的包容性版本。如果将它们放在名为 inclusive 的模块中,我看到两种可能的方法来命名函数本身:

  1. 将函数命名为 inclusive_rangeinclusive_xrange 以便客户端代码可以按如下方式使用它们:

    from inclusive import *
    ...
    inclusive_range(...)
    
  2. 将函数命名为 rangexrange:

    import inclusive
    ...
    inclusive.range(...)
    

对我来说,客户端代码的第二个示例看起来更好,但是我应该避免以这种方式重复使用内置名称吗?

您应该避免以这种方式重复使用内置函数名称,因为这会破坏您所依赖的任何库,并且会让其他人(或您将来)阅读和维护时感到非常困惑。但是,如果您必须这样做,您可以选择这样做。

可以,但这可能不是一个好主意。

问题是,如果其他人使用该库,他们可能会引入副作用

 from your_lib import inclusive range

 ..... lots of code .....

 range()    # ambiguous 

这里的问题是在您的模块中您将无法调用内置函数 range()xrange()。您描述的方式 inclusive.range() 看起来不错,但任何其他用户可能不会以相同的方式导入,他们也会遇到冲突。

inclusive.irange()inclusive.ixrange() 呢?

编辑:确实可以在自己的模块中使用 range() 如果您注意导入和重命名它们,但这可能是另一个迹象表明这可能是棘手的方法。

这变成了一些不同选项的列表,而不是直接的答案。然而,有两个概念是最重要的:

  • 用户应该能够替换 rangexrange 如果他们明确选择;但是
  • 用户不能implicitly/accidentally替换rangexrange

读者应该始终清楚他们的代码在何处使用内置函数以及在何处使用替换。

出于这个原因,我在下面概述的所有选项 防止 通配符导入 (from inclusive import *) 隐藏内置函数。哪个是您的最佳选择取决于您是否将替换内置函数视为模块的主要用途或次要用途。用户通常会想要替换内置插件,还是将它们一起使用?


在你的位置上,我想我会做到以下几点:

inclusive.py:

"""Inclusive versions of range and xrange."""

__all__ = []  # block 'from inclusive import *'

old_range, old_xrange = range, xrange  # alias for access

def range(...):  # shadow the built-in
    ...

def xrange(...):  # ditto
    ...

这允许用户:

  1. import inclusive 并访问 inclusive.rangeinclusive.xrange;
  2. from inclusive import range, xrange,清楚地替换了内置函数,没有任何令人不快的副作用;或
  3. from inclusive import range as irange, xrange as ixrange 一起使用内置版本和替换版本。

__all__ 定义为一个空列表意味着 from inclusive import * 不会 悄悄隐藏内置项。


如果您真的想要,您可以添加:

irange, ixrange = range, xrange

inclusive.py的末尾,修改__all__的定义为:

__all__ = ['irange', 'ixrange']

现在用户有两个额外的选择:

  • from inclusive import irange, ixrange(比上面选项 3 中的手动别名函数稍微简单);和
  • from inclusive import *(与上面相同的结果,仍然没有内置函数的隐式阴影)。

当然,您可以完全采用另一种方式 - 命名您自己的版本 irangeixrange,然后如果用户 真的想要 替换他们必须的内置函数:

from inclusive import irange as range, ixrange as xrange

这不需要您定义 __all__ 来避免通配符导入隐藏内置函数。