因此,我一直在对下划线字符(_
)进行一些研究。我知道它的大多数用例及其语义,因此我将它们放到下面作为回顾,最后我将得出一个问题,这个问题更多是关于两个用例的概念性问题。
gettext
的诸如_
之类的函数在十进制分组中以提高可见性(特别是进行3组分组,例如1_000_000)-请注意,仅从Python 3.6起,该功能才可用。
示例:
1_000_000 == 10**6 # equals True
x = 1_000
print(x) # yields 1000
要“忽略”某些值,尽管我不会将其称为“忽略”,因为这些值仍会被评估并绑定到_
,就像它是常规标识符一样。通常,我会找到比这更好的设计,因为我发现这是code smell。多年来,我很少使用这种方法,因此,我想每当您认为需要使用它时,就可以肯定地改进设计以免使用它。
示例:
for _ in range(10):
# do stuff without _
ping_a_server()
# outside loop that still exists and it still has the last evaluated value
print(_) # would yield 9
跟踪标识符(used by convention以避免名称与内置标识符或保留字冲突):
示例
class Automobile:
def __init__(self, type_='luxury', class_='executive'):
self.car_type = type_
self.car_class = class_
noob_car = Automobile(type_='regular', class_='supermini')
luxury = Automobile()
作为访问修饰符but only as a convetion,因为Python没有真正意义上的access modifiers:
单个下划线
Acts as a weak "internal use" indicator。星号(_
)会忽略所有以from M import *
开头的标识符
示例:
a.py
_bogus = "I'm a bogus variable"
__bogus = "I'm a bogus with 2 underscores"
___triple = 3.1415
class_ = 'Plants'
type_ = 'Red'
regular_identifier = (x for x in range(10))
b.py
from a import *
print(locals()) # will yield all but the ones starting with _
重要的概念观察
我讨厌人们称其为私有(不包括
实际上在Python中没有什么是私有的)。
如果以类推的话,这将等效于Java's protected,因为在Java中,protected的意思是“ 派生的类和/或在同一包中”。因此,由于在模块级别,任何带有下划线_
的标识符都具有与常规标识符不同的语义(而且我是从Python的角度讲语义,而不是从我们的角度来看CONSTANTS
和{{1} }的含义不同,但对于Python而言,它们是同一件事),并且在谈论开始导入时会被导入机制忽略,这实际上表明您应该在该模块内或在其定义的类内使用这些标识符。或其派生子类。
双下划线
无需赘述,这将调用名称处理机制 当在类中的标识符上使用时,这会更困难,但是 同样,对于人们来说,从类中访问属性 该基类的子类。
因此,我一直在阅读this book,专门针对初学者,在变量部分,作者说了类似的话:
变量可以以下划线_开头,尽管我们通常避免这样做,除非我们编写库代码供他人使用。
这让我想起了什么... 在私有项目中,甚至在没有被其他项目用作依赖项的开源项目中,将内容标记为非公开有意义吗? < / p>
例如,我有一个 open source web app ,我定期将更改推送到该位置。它主要用于教育目的,因为我想编写简洁的标准化代码,并将我在此过程中获得的任何新技能付诸实践。现在我想到了上述问题:使用标记事物为非公开的标识符有意义吗?
为了便于讨论,我们可以说,在将来,将有500个人积极地为该Web应用程序做出贡献,并且它在代码方面变得非常活跃。我们可以假设很多人将直接使用那些“受保护的”和“私有”的标识符(即使建议这样做,也不是所有人中的500名都知道最佳实践),但是因为这是一个非图书馆项目,所以< / strong>,这意味着它不是其他项目中的依赖项,也不是其他人使用的依赖项,可以在某种程度上让他们放心,因为这些方法不会在代码重构中消失,因为进行重构的开发人员可能会注意到该项目中的所有呼叫者,并将相应地进行重构(或者他不会注意到,但是测试会告诉他)。
显然,这在图书馆代码中是有意义的,因为所有人都取决于您的图书馆,所有可能的未来人都取决于您的图书馆,或者间接依赖您的图书馆的人(其他人将您的图书馆嵌入他们的图书馆并公开他们的图书馆)。库等),请注意,具有单尾划线或双尾划线的标识符是一种实现细节,可以随时更改。因此,他们应该始终使用您的公共API。
如果没有人可以从事这个项目,我将其私有化,并且我将是唯一一个从事该项目的人怎么办?或一小部分人。 在此类项目中使用访问修饰符指示符有意义吗?
答案 0 :(得分:5)
您的观点似乎是基于以下假设:私有或公共(或python中的等效建议)基于读写代码的开发人员。那是错误的。
即使您仅单独编写一个仅会使用的应用程序,如果设计正确,也会将其划分为模块,并且这些模块将公开接口并具有私有实现。
您同时编写了模块和使用该模块的代码,这并不意味着没有部分应该私有以保持封装。因此,是的,不管模块上开发人员的数量或依赖于该项目的开发人员数量如何,使用领先的下划线将模块的各个部分标记为私有都是有意义的。
编辑:
我们真正讨论的是encapsulation,它是python和任何其他语言的软件工程通用的概念。
这个想法是将整个应用程序分成几个部分(我正在谈论的模块,可能是python包,但也可能是设计中的其他东西),并确定执行目标所需的几种功能中的哪一个是在那里实现(称为Single Responsibility Principle)。
这是design by contract的好方法,这意味着确定模块要向软件的其他部分公开的抽象,并将不包含在其中的所有内容隐藏为实现细节。其他模块不应仅依靠公开的功能来依靠您的实现,这样,只要您想提高性能,支持新功能,改善可维护性或任何其他原因,就可以自由更改。
现在,所有这些理论都与语言无关,与应用程序无关,这意味着每次设计软件时,都必须依靠语言提供的功能来设计模块和构建封装。
Python,据我所知,是少数几个(即使不是唯一的)Python之一,做出了有意的选择(我认为不好),它不强制执行封装,但允许开发人员访问所有内容,正如您所知已经发现了。
但是,这并不意味着上述概念不适用,而只是不能在语言级别上强制实施,并且必须以更宽松的方式实施(作为简单建议)。
封装实现并自由使用每条可用信息是否意味着一个坏主意?显然不是,建立架构仍然是一个很好的SOLID原则。
所有这些都不是真正必要的,它们只是良好的原则,经过时间和经验的证明,它们可以创建高质量的软件。
您应该在小型应用程序中使用没有人使用它吗?如果您希望事情按原样完成,那么应该。
有必要吗?嗯,您可以在没有它的情况下使用它,但是您可能会发现,此后您会花费更多的精力。
如果我不是编写库而是编写完整的应用程序,那该怎么办?那么,这是否意味着您不应该以一种干净整洁的方式编写它?