当你有疑问时,保持“public” - 我的意思是,不要添加任何东西来隐藏你的属性名。如果你有一个带有一些内部值的类,请不要担心它。不要写成:
class Stack(object):
def __init__(self):
self.__storage = []
def push(self, value):
self.__storage.append(value)
写成默认值:
class Stack(object):
def __init__(self):
self.storage = []
def push(self, value):
self.storage.append(value)
这绝对是一种有争议的做法。Python新手讨厌它,甚至一些老Python程序员也鄙视这个默认值——但它仍然是默认值,所以我建议你遵循它,即使你感到不舒服。
如果您真的想向用户发送“不能触摸!”的消息,通常的方法是在变量前加一个下划线。这只是一种约定,但人们理解它,并在处理这种东西时特别小心。
class Stack(object):
def __init__(self):
self._storage = []
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有属性
今天,大多数面向对象语言采用相反的方法:不应该使用的东西不应该可见,所以属性应该是私有的。理论上,这将产生更易管理、耦合度更低的类,因为没有人会鲁莽地改变对象的值。
然而,情况并不那么简单。例如,Java类有许多只获取值的getter和只设置值的setter。你需要,假设,七行代码来声明一个属性 - 这是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应该很好,其余都是细节。
Guido说了算
这并不具有争议性: 他实际上是这么说的。(查找"公开kimono")
这是文化
是的,有一些原因,但没有关键原因。这主要是Python编程中的文化方面。坦率地说,也可以反过来问:为什么有些语言默认使用私有属性?对于Python实践的同样主要原因:因为这些语言的文化不同,每种选择都有优缺点。
既然已经有了这种文化,建议您遵循它。否则,当您在Stack Overflow上提问时,您会被Python程序员告知从您的代码中删除__
,这可能会让您感到恼火 :)