如何命名模块而不与变量名冲突?

3

我发现有时候为一个模块取名很难,因为之后容易与变量名冲突。例如,我有一个如下的类:

class Petition(object):
    def __init__(self, signature_count_requirement):
        self._signature_count_requirement = signature_count_requirement

以及下面的函数:

def check_if_someone_can_sponsor_a_petition(someone):
    pass

因此,编写如下代码是很自然的:

if check_if_someone_can_sponsor_a_petition(a):
    petition = Petition(3)

我希望将这个函数和 Petition 类放到一个模块中。那么我应该给这个模块起什么名字呢?将其命名为 petition 似乎很自然。但是后面很容易出现变量名称冲突,如下所示:

import petition
if petition.check_if_someone_can_sponsor_a_petition(a):
    petition = petition.Petition(3)  # this is ugly.

datetime模块可能是一个更好(或更糟?)的例子。当在代码中遇到名称datetime时,我经常需要确保它是模块名称、类名称还是某个变量名称。

是否有任何良好的约定来命名模块以避免与后面的变量名称冲突?


1
你可以这样更改导入的模块名称:import petition as m_petition - qvpham
@julivico 谢谢。我认为这是一个好习惯。下面的一个答案建议了同样的事情。下次我导入 datetime 时,我想将其作为 m_datetime 导入。但这需要导入模块的人注意一下。但人们经常犯错误,所以我认为更好的解决方法是以更好的方式命名模块。 - kkpattern
关键是要充分利用命名空间的优势。让我们考虑一下 requests。有人可能会认为 getpost 是模糊的名称,但归根结底,通过使用命名空间,可以得到干净、简洁和自我解释的调用 requests.get(url) - Łukasz Rogalski
这是一个非常好的问题。我每天都遇到这个问题。然而,没有好的解决方案,任何解决方案都是主观看法。StackOverflow不是问这个问题的正确场所。我希望这个问题可以在其他地方提出,但我不确定应该去哪里。http://martinfowler.com/bliki/TwoHardThings.html - Dima Tisnek
@qarma 我同意StackOverflow不是问这个问题的正确地方。但就像你说的,我不确定该去哪里问,而且StackOverflow上的人对编码非常有经验,所以我认为我可以在这里得到答案。到目前为止,我认为我可以使用“import as”来避免命名空间冲突。 - kkpattern
OT: check_if_someone_can_sponsor_a_petition 应该重命名。从使用(即调用站点)开始,可以是例如 petition.can_be_sponsored(...)(更好,但是什么是“can be”),因此 petition.is_sponsored(...)petition.is_valid(...) 后者意味着“遵循规则,因此理论上可以赞助”... 您可以采用面向对象编程,其中 petition 是一个对象,具有诸如 .valid.sponsored 以及一些方法的属性。 - Dima Tisnek
4个回答

3

你的代码实际上不会工作,因为将值赋给本地变量petition意味着Python将把对该名称的所有引用视为本地引用,因此不会找到模块的全局引用,从而导致NameError。

您可以使用不同的名称导入模块:

 import petition as petition_module

或者你可以直接导入你需要的东西:

 from petition import Petition, check_if_someone_can_sponsor_a_petition

如果您想要更加清晰明了,可以考虑将 check_if_someone_can_sponsor_a_petition 作为 Petition 的 classmethod。


是的,这个示例试图表明类似于“petition”的名称容易出错,因此我想要一个更好的名称。 - kkpattern

2

如果您不想使用这样的限定名称,也无需如此。例如,将您的模块命名为petitions,您可以编写以下代码:

from petitions import Petition, check_if_someone_can_sponsor_a_petition

这将把名称复制到您的本地命名空间中,因此编写以下内容是可以的:

if check_if_someone_can_sponsor_a_petition(a):
    petition = Petition(3)  # this is no longer so ugly.

当然,如果您将模块命名为petition,那么使用相同名称的变量将是一个非常糟糕的主意...

这个问题可以通过这种方式和方法import petition as pet来解决。但是需要导入模块的人要注意。但是人们经常会犯错误,所以我想要一个更好的名称来避免这种情况。也许直接将模块命名为m_petition - kkpattern
导入模块的人必须时刻注意可能存在的命名空间冲突。有许多解决方案可供选择,其中最有帮助的一种(因为您似乎想要使用完全限定名称)是使用适当的别名导入模块,即使用“import module_real_name as alias”。 - holdenweb

0

类名应该使用CapsWords约定书写,变量全部小写,函数使用下划线小写。我认为很多人使用尾随下划线来避免命名冲突。这可能不太美观,但这是PEP 8的约定。请参见下面的链接以获取有关命名约定的部分。

https://www.python.org/dev/peps/pep-0008/#prescriptive-naming-conventions

希望这能帮到你!


0

不确定是否回答了你的问题,但是你可以使用'as'指令导入模块,并定义你选择的本地名称:

import petition as pet

if pet.check_if_someone_can_sponsor_a_petition(a):
        petition = pet.Petition(3)

这可能解决你的命名冲突。


谢谢,我认为这是一个好习惯。但正如我在其他答案中所说的那样,它需要导入模块的人注意,并且人们经常犯错误,因此我考虑直接将模块命名为 m_petition - kkpattern

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