通过getter/setter访问私有变量

0 投票
3 回答
4406 浏览
提问于 2025-04-16 06:07

我有个关于在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 个回答

0

@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 替换成其他任何东西,而不会改变或破坏其他类使用的这个类的接口。

2

都不是。在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"
9

你不能拿一个经典的糟糕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怪物发表看法,我建议使用设置器——毕竟,这是你写的,它就是为了这个目的存在的!手动设置变量并没有明显的好处,反而有几个缺点。

撰写回答