如有疑问,请将其保留为“公开”-我的意思是,请勿添加任何内容以掩盖您的属性名称。如果您的类具有一些内部值,请不要理会。而不是写:
class Stack(object):
def __init__(self):
self.__storage = [] # Too uptight
def push(self, value):
self.__storage.append(value)
默认写这个:
class Stack(object):
def __init__(self):
self.storage = [] # No mangling
def push(self, value):
self.storage.append(value)
这无疑是一种有争议的做事方式。Python的新手只是讨厌它,甚至一些老的Python人士都鄙视了此默认设置-但这仍然是默认设置,因此即使您感到不舒服,我也建议您遵循它。
如果您确实要发送消息“无法触摸此!” 对于您的用户,通常的方法是在变量前加一个下划线。这只是一个约定,但是人们理解它并且在处理这些东西时要格外小心:
class Stack(object):
def __init__(self):
self._storage = [] # This is ok but pythonistas use it to be relaxed about it
def push(self, value):
self._storage.append(value)
这对于避免属性名称和属性名称之间的冲突也很有用:
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
那双下划线呢?好吧,双下划线魔术主要用于避免方法的意外重载和名称与超类的属性的冲突。。如果您编写一个预期会扩展很多次的类,这将非常有用。
如果您想将其用于其他目的,可以,但是既不推荐也不推荐使用。
编辑:为什么会这样?好吧,通常的Python风格并不强调将事情变成私有的-相反!造成这种情况的原因很多-大多数都引起争议...让我们看看其中的一些原因。
Python具有属性
如今,大多数OO语言都采用相反的方法:不应该使用的内容不应该可见,因此属性应该是私有的。从理论上讲,这将产生更易于管理,耦合更少的类,因为没有人会不顾一切地更改对象内部的值。
但是,它并不是那么简单。例如,Java类确实有很多的属性和 getter方法,只是得到的值和刚刚制定者设定的值。让我们说,您需要七行代码来声明一个属性-Python程序员会说这不必要地复杂。另外,实际上,您只需编写全部代码即可获得一个公共字段,因为您可以使用getter和setter更改其值。
那么,为什么要遵循这种默认的私有策略?默认情况下只需公开您的属性即可。当然,这在Java中是有问题的,因为如果您决定向属性添加一些验证,那么它将要求您更改所有
person.age = age;
在您的代码中,让我们说,
person.setAge(age);
setAge()
存在:
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
this.age = 0;
}
}
因此,在Java(和其他语言)中,默认设置是无论如何都使用getter和setter,因为它们可能很烦人,但是如果您遇到我所描述的情况,可以节省很多时间。
但是,由于Python具有属性,因此您不需要在Python中执行此操作。如果您有此类:
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
然后您决定验证年龄,则无需更改person.age = age
代码段。只需添加一个属性(如下所示)
class Person(object):
def __init__(self, name, age):
self.name = name
self._age = age if age >= 0 else 0
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if age >= 0:
self._age = age
else:
self._age = 0
如果您可以做到并且仍然使用 person.age = age
,为什么还要添加私有字段以及getter和setter?
(此外,请参阅Python并非Java,本文将介绍使用getter和setter的危害。)
一切都是可见的-试图隐藏只会使您的工作复杂化
即使在具有私有属性的语言中,您也可以通过某种反射/自省库来访问它们。人们在框架和解决紧急需求方面做了大量工作。问题在于,自省库只是完成公共属性所能做的一种困难的方法。
由于Python是一种非常动态的语言,因此将负担加到类中只会适得其反。
无法看到问题-这是必需的看到
对于Pythonista,封装不是无法看到类的内部,而是避免查看它的可能性。我的意思是说,封装是组件的属性,它使用户无需担心内部细节即可使用它。如果您可以使用某个组件而不必担心自己的实现,那么它将被封装(Python程序员认为)。
现在,如果您以这样的方式编写类,就可以使用它而不必考虑实现细节,那么出于某种原因想要查看类内部就没有问题。关键是:您的API应该不错,其余的就是细节。
圭多这样说
好吧,这没有争议:实际上他是这么说的。(寻找“开放和服”。)
这是文化
是的,有一些原因,但没有关键原因。这主要是Python编程的文化方面。坦白说,也可能是另一种方式,但事实并非如此。同样,您也可以轻松地反过来问:为什么某些语言默认使用私有属性?出于与Python实践相同的主要原因:因为这是这些语言的文化,每种选择都有其优点和缺点。
由于已经存在这种文化,因此建议您遵循它。否则,__
当您在Stack Overflow中提问时,Python程序员会告诉您将其从代码中删除,这会使您感到烦恼:)