是否有Python命名约定以避免与标准模块名称冲突?

26

PEP 8建议使用单个下划线以避免与Python关键字冲突,但是对于标准Python模块的模块名称冲突呢?是否也应该使用单个下划线?

我想象中的情况是这样的:

import time
time_ = time.time()

1
+1 为你提出 PEP 8 表示赞赏 - 你在回答我的问题时,通过提到它来问我问题!现在我必须回去将所有的 _file_id 局部变量重命名为 file_id_ - ArtOfWarfare
2个回答

13

PEP 8似乎没有直接涉及这个问题。

当你的代码与一个关键字冲突时,结尾的下划线显然是必要的,因为否则你的代码会引发一个SyntaxError(或者如果你运气不好,编译成完全不同于你所期望的东西)。

因此,即使在你有一个类属性、实例属性、函数参数或本地变量想要命名为class的情况下,你也必须使用class_

但是对于time来说并非如此。我认为在这些情况下,你不应该为time添加后缀下划线。

有先例——标准库中的多个类都有名为time的方法或数据属性(而且没有一个是time_)。


当然,还有一种情况,你在创建一个与模块相同范围的名称(通常意味着全局变量或函数)。那么你就有更多混淆的可能性,并隐藏了访问time模块的能力,直到当前范围结束。

我认为90%的情况下,答案会是“那不应该是一个全局变量”。


但是这仍然留下了另外10%的情况。

还有一种情况,你的名称在一个受限命名空间中,但是该命名空间是一个函数内部的本地作用域,你需要访问time模块。

或者,在一个复杂的长函数中(你不应该有这样的函数,但是……有时候你确实会有),如果对人类读者不明显time是一个本地名称而不是模块,那就像混淆解释器一样糟糕。

在这里,我认为剩下的99%的时间,答案是“选择一个不同的名称”。

例如,看看这段代码:

def dostuff(iterable):
    time = time.time()
    for thing in iterable:
        dothing(thing)
    return time.time() - time # oops!
显而易见的解决方法是重新命名变量为startt0或其他有意义的名称,这样不仅可以解决问题,还能使名称更有意义。
但这仍然留下了1%的情况。例如,有些库会根据协议规范或.NET或ObjC接口生成Python代码,其中名称不能由您控制;您所能做的就是对翻译后的名称应用某种程序化且明确的规则。在这种情况下,我认为在stdlib模块名称和关键字后追加_作为规则可能是一个好主意。
您可能还可以想出其他例子,其中变量无法随意重命名,必须(至少可能)与time模块处于相同的作用域等等。在任何这样的情况下,我会选择使用_后缀。

那么你的意思是,如果我需要在函数中创建一个本地变量,我应该只使用名称time并覆盖该函数的其余部分的包? - chappy
@chappy:好吧,我认为你应该“选择一个不同的名称”。而且你应该有大多数合理短小简单的函数,在这种情况下,“clobbering”可能没有任何影响——更重要的是,这种非差异性应该对任何人类读者都是显而易见的。在极少数情况下,如果两者都不适用,那么当然可以使用time_。但我怀疑你在编码的整个生命周期中永远不会遇到这种情况。 - abarnert
@chappy:显然我的回答没有表达清楚,我应该这样做的,所以让我试着重新写一下。 - abarnert

0
根据PEP8的规定进行回答。
time_这个例子中,使用了单个尾随下划线。
PEP中对此的描述如下:

single_trailing_underscore_:按照惯例用于避免与Python关键字冲突,例如:

tkinter.Toplevel(master, class_='ClassName')

https://peps.python.org/pep-0008/#descriptive-naming-styles


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接