Я из мира Java и читаю паттерны, рецепты и идиомы Брюса Экелса « Python 3» .
Читая о классах, можно сказать, что в 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?
Ответы:
Это культурно. В Python вы не пишете в экземпляр класса или переменные класса. В Java ничто не мешает вам делать то же самое, если вы действительно этого хотите - в конце концов, вы всегда можете отредактировать исходный код самого класса для достижения того же эффекта. Python отказывается от претензий на безопасность и призывает программистов быть ответственными. На практике это работает очень хорошо.
Если по какой-то причине вы хотите эмулировать закрытые переменные, вы всегда можете использовать
__
префикс из PEP 8 . Python изменяет имена переменных, например,__foo
так, чтобы они не были легко видны для кода вне класса, который их содержит (хотя вы можете обойти это, если вы достаточно решительны, точно так же, как вы можете обойти защиту Java, если работаете над этим ).В соответствии с тем же соглашением
_
префикс означает « держаться подальше», даже если вы технически не защищены от этого . Вы не играете с переменными другого класса, которые выглядят как__foo
или_bar
.источник
Закрытые переменные в python - это более или менее хак: интерпретатор намеренно переименовывает переменную.
Теперь, если вы попытаетесь получить доступ
__var
вне определения класса, произойдет сбой:Но вы можете легко сойти с рук:
Вы, вероятно, знаете, что методы в ООП вызываются следующим образом:
x.printVar() => A.printVar(x)
если выA.printVar()
можете получить доступ к какому-либо полю внутриx
, к этому полю также можно получить доступ извнеA.printVar()
... в конце концов, функции созданы для повторного использования, внутри операторов нет особой власти.Игра отличается, когда задействован компилятор ( конфиденциальность - это концепция уровня компилятора ). Он знает об определении класса с модификаторами контроля доступа, поэтому он может выдавать ошибку, если правила не соблюдаются во время компиляции
источник
Как правильно сказано во многих комментариях выше, давайте не будем забывать о главной цели модификаторов доступа: помочь пользователям кода понять, что должно измениться, а что нет. Когда вы видите приватное поле, вы не возитесь с ним. Так что это в основном синтаксический сахар, который легко достигается в Python с помощью _ и __.
источник
В соглашении подчеркивания есть вариация приватных переменных.
Есть некоторые тонкие различия, но ради идеологической чистоты шаблона программирования достаточно.
Существуют примеры декораторов @private, которые более близко реализуют эту концепцию, но YMMV. Можно также написать определение класса, которое использует мета
источник
__x
поскольку переменная внутри классаA
на самом деле переписывается компилятором_A__x
, она все еще не является полностью закрытой и может быть доступна._A__x
, я не буду ее трогать. Это может быть заразно. Я убегу к черту от этого.«В Java нас учили о публичных / частных / защищенных переменных»
"Почему это не требуется в Python?"
По той же причине это не требуется в Java.
Вы можете использовать - или не использовать
private
иprotected
.Как программист Python и Java, я обнаружил , что
private
иprotected
очень, очень важные концепции дизайна. Но на практике, в десятки тысяч строк Java и Python, я никогда на самом деле использовалиprivate
илиprotected
.Почему бы нет?
Вот мой вопрос "защищен от кого?"
Другие программисты в моей команде? У них есть источник. Что означает защищенный, когда они могут изменить это?
Другие программисты в других командах? Они работают в одной компании. Они могут - с помощью телефонного звонка - получить источник.
Клиенты? Это программирование по найму (как правило). Клиенты (как правило) владеют кодом.
Так от кого именно я это защищаю?
источник
Как упомянуто ранее, вы можете указать, что переменная или метод являются закрытыми, добавив префикс подчеркивания. Если вы чувствуете, что этого недостаточно, вы всегда можете использовать
property
декоратор. Вот пример:Таким образом, кто-то или что-то, на что ссылается,
bar
на самом деле ссылается на возвращаемое значениеbar
функции, а не на саму переменную, и поэтому к нему можно получить доступ, но нельзя изменить. Однако, если кто-то действительно хочет, он может просто использовать_bar
и присвоить ему новое значение. Не существует надежного способа запретить кому-либо доступ к переменным и методам, которые вы хотите скрыть, как уже неоднократно говорилось. Тем не менее, использованиеproperty
- это самое ясное сообщение, которое вы можете отправить, что переменная не подлежит редактированию.property
также может использоваться для более сложных путей доступа для получения / установки / удаления, как описано здесь: https://docs.python.org/3/library/functions.html#propertyисточник
Python имеет ограниченную поддержку частных идентификаторов, благодаря функции, которая автоматически добавляет имя класса к любым идентификаторам, начинающимся с двух подчеркиваний. По большей части это прозрачно для программиста, но чистый эффект состоит в том, что любые переменные, названные таким образом, могут использоваться как частные переменные.
Смотрите здесь для получения дополнительной информации об этом.
В общем, реализация объектной ориентации в Python немного примитивна по сравнению с другими языками. Но на самом деле мне это нравится. Это очень концептуально простая реализация и хорошо вписывается в динамический стиль языка.
источник
Единственный раз, когда я использую закрытые переменные, это когда мне нужно делать что-то другое при записи или чтении из переменной, и поэтому мне нужно принудительно использовать установщик и / или получатель.
Опять же, это относится к культуре, как уже говорилось. Я работал над проектами, где чтение и запись переменных других классов были бесплатными для всех. Когда одна реализация устарела, потребовалось намного больше времени для определения всех путей кода, которые использовали эту функцию. Когда использование сеттеров и геттеров было принудительным, можно было легко написать оператор отладки, чтобы идентифицировать, что устаревший метод был вызван, и путь к коду, который его вызывает.
Когда вы находитесь в проекте, где каждый может написать расширение, уведомление пользователей о устаревших методах, которые должны исчезнуть в нескольких выпусках, следовательно, жизненно важно, чтобы поломка модуля была минимальной после обновлений.
Итак, мой ответ: если вы и ваши коллеги поддерживаете простой кодовый набор, тогда защита переменных класса не всегда необходима. Если вы пишете расширяемую систему, тогда становится необходимым, когда вносятся изменения в ядро, которые должны быть отслежены всеми расширениями, использующими код.
источник
Извините, ребята, за "воскрешение" темы, но, надеюсь, это кому-нибудь поможет:
В Python3, если вы просто хотите «инкапсулировать» атрибуты класса, как в Java, вы можете просто сделать то же самое, как это:
Чтобы создать это, сделайте:
Обратите внимание, что:
print(ss.__s)
выдаст ошибку.На практике Python3 будет скрывать глобальное имя атрибута. Превращая это как "приватный" атрибут, как в Java. Имя атрибута по-прежнему глобально, но недоступно, как частный атрибут в других языках.
Но не бойся этого. Это не важно Это тоже делает работу. ;)
источник
частные и защищенные концепции очень важны. Но python - всего лишь инструмент для создания прототипов и быстрой разработки с ограниченными ресурсами, доступными для разработки, поэтому некоторые уровни защиты не так строги в Python. Вы можете использовать «__» в классе, он работает правильно, но выглядит недостаточно хорошо - каждый доступ к такому полю содержит эти символы.
Кроме того, вы можете заметить, что концепция ООП Python не идеальна, смальта или рубин намного ближе к концепции чистого ООП. Даже C # или Java ближе.
Python очень хороший инструмент. Но это упрощенный язык ООП. Синтаксически и концептуально упрощено. Основная цель существования Python - предоставить разработчикам возможность быстро и легко писать легко читаемый код с высоким уровнем абстракции.
источник
В Python нет личных переменных, таких как C ++ или Java. Вы можете получить доступ к любой переменной-члену в любое время, если хотите. Тем не менее, вам не нужны закрытые переменные в Python, потому что в Python неплохо представить переменные-члены ваших классов. Если у вас есть необходимость инкапсулировать переменную-член, вы можете сделать это позже, используя "@property", не нарушая существующий клиентский код.
В python одиночное подчеркивание «_» используется для указания того, что метод или переменная не рассматриваются как часть публичного API класса и что эта часть API может меняться в разных версиях. Вы можете использовать эти методы / переменные, но ваш код может сломаться, если вы используете более новую версию этого класса.
Двойное подчеркивание «__» не означает «частная переменная». Вы используете его для определения переменных, которые являются «локальными по классу» и которые не могут быть легко переопределены подклассами. Это искажает имя переменных.
Например:
Имя self .__ foobar автоматически искажается до self._A__foobar в классе A. В классе B оно искажается до self._B__foobar. Таким образом, каждый подкласс может определять свою собственную переменную __foobar без переопределения своих родительских переменных. Но ничто не мешает вам получить доступ к переменным, начинающимся с двойного подчеркивания. Однако искажение имен не позволяет вам вызывать эти переменные / методы случайно.
Я настоятельно рекомендую посмотреть выступление Рэймонда Хеттингера «Инструментарий разработки классов Pythons» из Pycon 2013 (должен быть доступен на Youtube), в котором приведен хороший пример, почему и как следует использовать переменные экземпляра @property и «__».
источник
@property
это частью стандартного Python, или это специфично для IDE?property
встроенную функцию, которая доступна с python 2.2На самом деле вы можете смоделировать
C#
геттер и сеттер, используя этот простой трюк:Затем используйте его как в
C#
:Это просто объявление статической локальной переменной в функции, которая будет играть роль get / set, поскольку это единственный способ поделиться переменной с помощью методов get и set, не делая ее глобальной для класса или файла.
источник