Есть ли в Python «закрытые» переменные в классах? - PullRequest
490 голосов
/ 29 октября 2009

Я из мира Java и читаю Шаблоны, рецепты и идиомы Брюса Экелса

Читая о классах, можно сказать, что в Python нет необходимости объявлять переменные экземпляра. Вы просто используете их в конструкторе, и бум, они там.

Так, например:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

Если это так, то любой объект класса Simple может просто изменить значение переменной s вне класса.

Например:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

В Java нас учили о публичных / приватных / защищенных переменных. Эти ключевые слова имеют смысл, потому что иногда вам нужны переменные в классе, к которым никто за пределами класса не имеет доступа.

Почему это не требуется в Python?

Ответы [ 11 ]

3 голосов
/ 27 июня 2018

В Python нет закрытых переменных, как в C ++ или Java. Вы можете получить доступ к любой переменной-члену в любое время, если хотите. Тем не менее, вам не нужны закрытые переменные в Python, потому что в Python неплохо представить переменные-члены ваших классов. Если у вас есть необходимость инкапсулировать переменную-член, вы можете сделать это позже, используя "@property", не нарушая существующий клиентский код.

В python одиночное подчеркивание "_" используется для указания того, что метод или переменная не рассматривается как часть общедоступного API класса и что эта часть API может изменяться между различными версиями. Вы можете использовать эти методы / переменные, но ваш код может сломаться, если вы используете более новую версию этого класса.

Двойное подчеркивание "__" не означает "частная переменная". Вы используете его для определения переменных, которые являются «локальными по классу» и которые не могут быть легко переопределены подклассами. Он искажает имя переменной.

Например:

class A(object):
    def __init__(self):
        self.__foobar = None # will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # will be automatically mangled to self._B__foobar

self .__ Имя foobar автоматически передается self._A__foobar в классе A. В классе B оно передается self._B__foobar. Таким образом, каждый подкласс может определять свою собственную переменную __foobar без переопределения своих родительских переменных. Но ничто не мешает вам получить доступ к переменным, начинающимся с двойного подчеркивания. Однако искажение имен не позволяет вам вызывать эти переменные / методы случайно.

Я настоятельно рекомендую посмотреть, как Рэймонд Хеттингерс выступит с докладом «Инструментарий разработки классов Pythons» из Pycon 2013 (должен быть доступен на Youtube), где приведен хороший пример, почему и как следует использовать переменные экземпляра @property и «__».

...