通过getter/setter访问私有变量
我有个关于在Python中正确编程方式的问题... 可能会有不同的看法,但我还是想说说我的想法:
假设我有一个类,这个类里有几个私有属性,并且我实现了两个获取和设置的方法(不是通过重载 __getattr__
和 __setattr__
,而是用更“Java风格”的方式):
class MyClass:
def __init__(self):
self.__private1 = "Whatever1"
def setPrivate1(self, private1):
if isinstance(private1, str) and (private1.startswith("private")):
self.__private1 = private1
else:
raise AttributeError("Kaputt")
def getPrivate1(self):
return self.__private1
接下来假设在这个类的另一个方法中,我需要重新设置“__private1”的值。因为是在同一个类里,我仍然可以直接访问私有属性 self.__private1。
我的问题是:我应该使用:
self.setPrivate1("privateBlaBlaBla")
还是直接访问:
self.__private1 ="privateBlaBlaBla"
因为我是设置新值的人,我知道这个值(“privateBlaBlaBla”)是正确的(是一个以“private”开头的字符串),所以不会让系统变得不一致。另一方面,如果另一个程序员接手我的代码,需要更改 self.__private1 属性的功能,他就得逐行检查代码,看看 __private1 的值是否在其他地方被手动设置过。
我猜正确的做法是总是使用 setPrivate1 方法,只有在获取和设置时直接访问 __private1 变量,但我想听听更有经验的 Python 程序员的看法。
3 个回答
@unutbu 提供了一个很好的回答,但我有一点不同的看法。我认为当你使用设置器和属性的方法时,self._private1 = "Whatever1"
可以在 __init__
方法中替换成 self.private1 = "Whatever1"
。下面是重新写过的类:
class MyClass:
def __init__(self, private):
self.private1 = private
@property
def private1(self):
return self._private1
@private1.setter
def private1(self, private1):
self._private1 = private1 or 'NA'
这样做可以让你把 _private1 替换成其他任何东西,而不会改变或破坏其他类使用的这个类的接口。
都不是。在Python中,使用属性,而不是获取器和设置器。
class MyClass:
def __init__(self):
self._private1 = "Whatever1"
@property
def private1(self):
return self._private1
@private1.setter
def private1(self, private1):
if isinstance(private1, str) and (private1.startswith("private")):
self._private1 = private1
else:
raise AttributeError("Kaputt")
然后在你的代码中,用下面的方式设置 _private1
属性:
self.private1="privateBlaBlaBla"
你不能拿一个经典的糟糕Python例子出来,然后指望大家对该怎么处理它发表意见。建议使用获取器和设置器。
class MyClass:
def __init__(self):
self._private1 = "Whatever1"
@property
def private1(self):
return self._private1
@private1.setter
def private1(self, value):
self._private1 = value
顺便说一句,使用双下划线命名可能会让人困惑,因为Python会对这个名字进行处理,防止你从类外部访问它们。这其实并没有提供真正的安全性,但会让人很头疼。避免这种麻烦的最简单方法是使用单下划线命名,这基本上是一个通用的约定,用来表示私有
(大致如此)。
如果你想听听意见——那就用属性吧=)。如果你想对你的JavaPython怪物发表看法,我建议使用设置器——毕竟,这是你写的,它就是为了这个目的存在的!手动设置变量并没有明显的好处,反而有几个缺点。