为什么在Python中没有显式的访问修饰符:


28

如果“显式优于隐式”,为什么Python中没有显式访问修饰符:Public,Protected,Private等?

我知道想法是程序员应该通过提示知道该怎么做-无需使用“蛮力”。但是,IMO的“封装”或“信息隐藏”不仅是要使人们远离,而且还是组织和结构的问题:您的开发层应该具有自定义的,明确界定的范围和边界,就像物理系统一样。

有人可以在这里为我提供可靠的解释,为什么在Python中这种隐含的访问限制不是隐式的,而是隐式的?

编辑:到目前为止,我已经看到了3个建议的答案,并且我意识到我的问题有两个部分:

  1. 例如,为什么没有关键字

    private def myFunc(): 
        dostuff....
    

    而不是国际海事组织的丑陋和难以键入的下划线。但这不是重点。

  2. 更重要的是:

    为什么这些访问修饰符仅是“建议”或提示而没有执行。以后很难改变吗?将“受保护”更改为“公共”非常简单-如果您的继承链复杂,设计困难,则设计很糟糕-应该完善设计,而不要依赖于易于编写的语言功能结构不良的代码。

    强制使用访问修饰符后,您的代码将自动划分开-您知道某些段不在范围内,因此除非有必要,否则不必处理它们。而且,如果您的设计不好,并且发现自己不断将事物移入和移出不同的范围,那么该语言可以帮助您清理行为。

尽管我很喜欢Python,但我发现第二点是一个严重的缺陷。我还没有看到一个很好的答案。


Python中访问说明符的可能重复项 ...已关闭,因为它不是建设性的。
Frank Shearar

2
@弗兰克,这是对这个问题的再询问,以尝试更具建设性。我已经继续并删除了原始问题。

@Mark Trapp:好的。感谢您的澄清。我看不到如何取消我的关闭投票。
Frank Shearar

@Frank它将自行老化。
亚当李尔

问题private def whatever在于,这class x: def whatever(self): pass是的捷径class x: pass; x.whatever = lambda self: pass,因此,基本上,您需要一个私人修改器来进行分配
keppla 2011年

Answers:


22

“显式胜于隐式”只是Python设计哲学中的一句格言。“简单胜于复杂”也在那里。而且,尽管它不在Python的Zen中,但是“我们都同意成年人在这里”是另一个。

在这里,第二条规则可能是最重要的。在设计课程时,我对如何使用它有所了解。但是我无法预测所有可能的用途。这可能是一些未来使用我的代码需要访问我认为是私有变量。如果将来的程序员(甚至我将来)需要它们,为什么要使它们变得很难甚至根本无法访问?最好的做法是用警告标记它们-正如Joonas所指出的那样,一个下划线前缀是标准-它们是内部的,并且可能会更改。但是完全禁止访问似乎是不必要的。


1
“简单胜于复杂”和“所有人都同意这里的成年人”是为什么Smalltalk没有访问修饰符的原因。将方法放在“私有”类别中是一个提示,提示您在使用它之前应该考虑三次,仅此而已。
Frank Shearar

@Frank:“将方法放在“私有”类别中是一个提示,您应该在使用它之前先考虑三次,而不必再做其他事情了。”对我来说,这仅意味着当我不进行交易时,我不必担心它用它。
矢量

8
禁止访问私有成员有一个很好的理由:因为这可能会破坏类不变式。如果您不能编写私有成员,则不能确保您的类行为正确。
2012年

7
“如果将来的程序员(甚至我未来)需要它们,为什么要使它们变得很难甚至根本无法访问?” 因为设计的基本原理之一是接口(一段代码提供的内容)和实现(它如何提供它)之间的分离。封装通过减少代码不同部分之间的依赖关系来降低代码的复杂性。因此,使用public和private正是为了通过仅查看所需内容来简化代码。
Giorgio'5

3
不能再有更多不同了。访问修饰符提出了两种可能最能理解的概念来减少大型软件的复杂性:封装和关注点分离。不能提供这两种服务都不意味着python不是一种好的OOP语言,也不适合构建大型软件,这没有错。但是用诸如“为什么在不需要时增加复杂性呢?”之类的典型爱好者的论据来证明缺乏这些功能是合理的。是错的
Daniel Shin

10

我怀疑缺少访问修饰符的主要原因是简单性

如您所说,这不是要让人们离开,而是要与组织保持联系,因此“私有”的要点是,它会向您的api用户发送一条消息,“请不要编写依赖于此的代码”。

说“按照惯例,不应在类外使用_x或__x”是很简单的,但是在python的动态对象模型中,甚至很难想出一个符号。

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

如何记录可访问性?

我想这是个折衷方案。如果您严格不能使用它,我建议使用ruby,它的抽象和动态程度相似,但是具有对象模型,可以进行访问修改。


8
我认为这是正确的,但是IMO,这很糟糕。对于使用雅致和易读性为卖点的语言,编写__method__看起来很令人发指且晦涩。
jiggy

2
那不是惯例,__x__而是“魔术”(即调用方法以实现语言集成,例如运算符重载,可迭代性等)。约定是_x
keppla 2011年

6
抱歉,我仍然对Python有所了解。我正在努力尝试喜欢它,但是像这样的东西有点让人生气。特别是现在,我需要记住一个方法有多少个下划线的含义。就OP而言,似乎显式修饰符会更清晰。精简固然很棒,但不能胜过清晰。与构建代码相比,您在代码维护上的投入要多10倍。
jiggy

2
我的示例不是要显示下划线的不同计数,而是__init__偶然使用。该示例设置了对象的某些属性,而这些属性在编译时是未知的,因此显式访问修饰符将无济于事。
keppla 2012年

5
@jiggy:“我正努力地喜欢它”。我尝试了2年-然后放弃了。:-(似乎是一种脚本语言,被破解后的行为有点像真正的OOP语言。我无法想象用Python编写设计合理且易于阅读的大型复杂应用程序。正如您所说,“您的工作量增加了10倍以上维护代码而不是构建代码。简单的OOP和类型安全概念需要疯狂的破解和变通办法
矢量图片

8

Python约定是对受保护/私有成员使用下划线前缀。

这种约定,当后面,是因为访问修饰符有效地相同,除了1),你会直接从会员的看名字是否是公开与否,和2)你可以打破“封装”如果你真的想(这可能是合理的例如测试;使用其他语言,则必须使用反射==更多代码)。

最终,这是一个品味问题,但是如果您可以在没有特殊关键字的情况下做同样的事情(具有更多的灵活性),那么语言会更小,代码也会更简洁,这通常是一件好事。


2
“如果不使用特殊关键字就可以做同样的事情(灵活性更高),那么语言将更小,代码将更简洁”,我认为这通常是不正确的。(即使使用访问修饰符的特殊情况也是如此)
BenjaminB
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.