因此,我已经对下划线字符(_)进行了一些研究。我知道它的大多数用例及其语义,因此我将它们放到下面作为回顾,最后我将得出一个问题,该问题更多是关于两个用例的概念性问题。
gettext别名为_在十进制分组中以提高可见性(特别是进行3组分组,例如1_000_000)- 请注意,仅从Python 3.6开始可用。
例:
1_000_000 == 10**6 # equals True
x = 1_000
print(x) # yields 1000
Run Code Online (Sandbox Code Playgroud)为了“忽略”某些值,尽管我不会将其称为“忽略”,因为这些值仍会_像常规标识符一样进行评估和绑定。通常,我会找到比这更好的设计,因为我发现这是一种代码味道。多年来,我很少使用这种方法,因此,我想每当您认为需要使用它时,肯定可以改进设计以不使用它。
例:
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
Run Code Online (Sandbox Code Playgroud)尾随一个标识符(习惯上是为了避免名称与内置标识符或保留字冲突):
例
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()
Run Code Online (Sandbox Code Playgroud)作为访问修饰符,但仅作为对流,因为Python没有真正意义上的访问修饰符:
单首划线
充当弱的“内部使用”指示符。_星号导入(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 _
Run Code Online (Sandbox Code Playgroud)
重要的概念观察
当人们称其为私有时,我讨厌它(不包括Python中实际上没有私有的事实)。如果以类推的话,这将等效于Java的protected,因为在Java中,protected表示“ 派生类和/或在同一包内 ”。如此以来,在模块级与领先的下划线任何标识_具有比常规标识符不同的语义(我从Python的角度看不是我们的角度谈论语义地方CONSTANTS和global_variable 意思是不同的东西,但对于Python,它们是同一件事),并且在谈论开始导入时会被导入机制忽略,这实际上表明您应该在模块中或在或中定义的类中使用这些标识符。它们的派生子类。
双领先下划线
无需赘述,当在类中的标识符上使用时,这会调用名称处理机制,这使难度增加,但同样,对于从基类的子类继承的类,人们也无法访问属性。
因此,我一直在阅读这本面向初学者的书,在变量部分,作者说过:
变量可以以下划线_开头,尽管我们通常避免这样做,除非我们编写供他人使用的库代码。
是什么让我想起了…… 在私有项目中甚至在不被其他项目用作依赖项的开源项目中将内容标记为非公开有意义吗?
例如,我有一个开源Web应用程序,我定期将更改推送到该应用程序。它主要用于教育目的,因为我想编写简洁,标准化的代码,并将我在此过程中获得的任何新技能付诸实践。现在,我想到了上述问题:使用标记事物为非公开的标识符是否有意义?
为了便于讨论,我们可以说,在将来,将有500个人积极地为该Web应用程序做出贡献,并且它在代码方面变得非常活跃。我们可以假设大量的人将直接使用那些“受保护的”和“私有”的标识符(即使建议这样做,但并非所有人中的500名都知道最佳实践),但是由于这是一个非图书馆项目,因此并非如此在依赖于其他项目或其他人使用的项目时,可以在某种程度上让他们“放心”,因为这些方法不会在代码重构中消失,因为进行重构的开发人员很可能会注意到项目中的所有调用者,并且将相应地重构(或者他不会注意到,但是测试会告诉他)。
显然,这在图书馆代码中是有道理的,因为所有人都取决于您的图书馆,所有可能的未来人都取决于您的图书馆,或者间接取决于您的图书馆的人(其他人将您的图书馆嵌入他们的图书馆并公开他们的图书馆,等等。请注意,带有单个尾部下划线或双尾部下划线的标识符是实现细节,可以随时更改。因此,他们应始终使用您的公共API。
如果没有人会从事这个项目,我将其私有化,并且我将是唯一一个从事该项目的人怎么办?或一小部分人。在此类项目中使用访问修饰符指示器是否有意义?
您的观点似乎基于这样的假设:私有或公共(或python中的等效建议)基于读取和编写代码的开发人员。那是错的。
即使您只编写了仅会使用的单个应用程序,但如果设计正确,它也将被划分为模块,并且这些模块将公开接口并具有私有实现。
您同时编写了模块和使用该模块的代码的事实并不意味着没有部分应该私有以保持封装。因此,是的,不管模块上开发人员的数量或依赖于该项目的开发人员数量如何,都有一个领先的下划线将模块的各个部分标记为私有是有意义的。
编辑:
我们真正讨论的是封装,它是python和任何其他语言的软件工程通用的概念。
想法是将整个应用程序划分为多个部分(我正在谈论的模块,可能是python程序包,也可能是设计中的其他内容),并确定在其中实现执行目标所需的几种功能中的哪一项(这就是所谓的“ 单一责任原则”)。
这是按合同进行设计的一种好方法,这意味着决定模块将要公开给软件其他部分的抽象,并将不包含在其中的所有内容隐藏为实现细节。其他模块不应仅依靠公开的功能来依赖于您的实现,这样,无论何时您想提高性能,支持新功能,改善可维护性或任何其他原因,都可以自由更改。
现在,所有这些理论上的限制都与语言和应用程序无关,这意味着,每次设计软件时,都必须依靠语言提供的功能来设计模块和构建封装。
就我所知,Python是为数不多的(即使不是唯一的)Python之一,也是经过深思熟虑的选择(我认为不好),它不强制执行封装,但允许开发人员访问一切,正如您已经发现的。
但是,这并不意味着上述概念不适用,而只是作为简单的建议,它们不能在语言级别上强制执行,而必须以更宽松的方式实现。
封装实现并自由使用每条可用信息是否意味着不好?显然不是,它仍然是构建体系结构的良好SOLID原则。
所有这些都不是真正必要的,它们只是良好的原则,经过实践证明,经过长时间和经验,可以创建高质量的软件。
您是否应该在小型应用程序中使用没有其他人使用它?如果您希望事情按原样完成,那么应该。
他们有必要吗?好的,您可以使它在不使用的情况下工作,但是您可能会发现,以后它将花费更多的精力。
如果我不是在编写库而是在完成应用程序,该怎么办?好吧,这是否意味着您不应该以一种干净,整洁的方式编写它?
| 归档时间: |
|
| 查看次数: |
135 次 |
| 最近记录: |