Есть ли у Python «частные» переменные в классах?

Я пришел из мира Java и читаю Python 3 Patterns, Recipes and Idioms Брюса Экелса.

Читая о классах, он продолжает говорить, что в 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?


person Omnipresent    schedule 29.10.2009    source источник
comment
Вы имели в виду переменные экземпляра, а не переменные класса, верно?   -  person PaulMcG    schedule 13.11.2009
comment
Краткий и четкий ответ можно найти здесь. Я надеюсь, это поможет.   -  person Premkumar chalmeti    schedule 11.12.2019


Ответы (12)


Это культурно. В Python вы не пишете в экземпляры или переменные класса других классов. В Java ничто не мешает вам сделать то же самое, если вы действительно захотите - в конце концов, вы всегда можете отредактировать исходный код самого класса для достижения того же эффекта. Python отказывается от претензий на безопасность и призывает программистов нести ответственность. На практике это работает очень хорошо.

Если вы по какой-то причине хотите эмулировать частные переменные, вы всегда можете использовать префикс __ из PEP 8. Python изменяет имена переменных, таких как __foo, так что их нелегко увидеть для кода за пределами класса, который их содержит (хотя вы можете обойти это, если достаточно решительно настроены, как и вы можете обойти защиту Java, если над этим поработаете).

По тому же соглашению префикс _ означает держитесь подальше, даже если вам это технически не препятствует. Вы не играете с переменными другого класса, которые выглядят как __foo или _bar.

person Kirk Strauser    schedule 29.10.2009
comment
В этом есть смысл. Однако я не думаю, что в java есть способ получить доступ к частным переменным вне класса (кроме фактического изменения источника класса, конечно). Здесь? - person Omnipresent; 29.10.2009
comment
Интересно, что я имею опыт работы с PHP, и мне интересно, как это работает на практике. Разве для классов не опасно иметь возможность изменять то, что было бы закрытыми членами, если бы используемый язык был чем-то другим, кроме Python? - person David Snabel-Caunt; 29.10.2009
comment
Не то, чтобы я об этом знал, но дело в том, что вы можете редактировать исходный код или даже скомпилированный байт-код. Ничто не остановит вас, если вы достаточно решительно настроены возиться с внутренностями этого класса. Так зачем тратить усилия на предотвращение этого, вместо того, чтобы полагаться на условности и тонкие механизмы, чтобы сказать: «Не делайте этого»! И когда дело доходит до этого, независимо от того, насколько плохая идея обычно может быть, иногда вы действительно действительно хотите возиться там, где вам не положено. - person Kirk Strauser; 29.10.2009
comment
@ Дэвид - предполагается, что мы все здесь взрослые. Не ломайте то, что не можете исправить! В этом случае это означает, что вам не следует возиться с такими частными членами, как __foo или _bar. Опять же, на практике это не делается без очень уважительной причины. Возможно, это не чисто теоретически, но я ни разу не видел реальной ситуации, когда это было бы проблемой. - person Kirk Strauser; 29.10.2009
comment
+1: Мы все взрослые. Ключевые слова private и protected являются интересными комментариями, как и ведущий _ в имени переменной. Python распространяется и запускается как исходный код. Нет файла .class, чтобы скрыть реализацию. - person S.Lott; 29.10.2009
comment
Я предпочитаю питон, но не думаю, что java-метод так же бессмысленен, как вы думаете. Объявление чего-то частного быстро сообщает кому-то, читающему код, что-то очень полезное: это поле изменяется только внутри этого класса. - person Ned; 13.11.2009
comment
То же самое с __foo в Python, а _bar означает, что вы можете, но, вероятно, не должны. - person Kirk Strauser; 13.11.2009
comment
@ Вездесущий, вы можете использовать отражение. - person rapadura; 22.03.2011
comment
Важно то, что вы пишете хороший код, который аккуратно и эффективно решает вашу проблему. Любой, кто захочет взломать ваш код, в конечном итоге это сделает. Но им, вероятно, стоило потратить время на правильное кодирование :-) - person nialloc; 27.08.2012
comment
возможно, слишком поздно, но модификаторы доступа в java имеют очень реальные последствия для безопасности, когда код Java выполняется в jvm с настроенным SecurityManager. код, выполняющийся при настройке SecurityManager, не может обойти ограничения модификатора доступа. - person jtahlborn; 12.08.2013
comment
Есть общедоступный, частный и защищенный для принудительного доступа вместо символа подчеркивания _volption_ Python соглашение. В отличие от Python, в Ruby. Видимость в PHP на многих интерпретируемых языках подобно Ruby, PHP есть концепция видимости, но не в Python, в Python у них есть культура - person dVaffection; 25.10.2013
comment
@dVaffection Если Иэн М. Бэнкс чему-то меня научил, так это тому, что Культура всегда побеждает. - person Rob Grant; 25.11.2014
comment
Также стоит отметить, что как более или менее интерпретируемый язык, многие соображения, которые может иметь компилятор C ++ (и, я полагаю, компилятор Java), просто не существуют в python. Частное свойство или метод могут иметь различные оптимизации для ускорения доступа из локального объекта. Он говорит: «Привет, компилятор, ко мне когда-либо будут обращаться только из этого объекта, так что не беспокойтесь о всех документах, которые сделают меня видимым снаружи, черт возьми, вы даже можете встроить меня, если это поможет». В случае с питонами это как бы спорный вопрос. - person Shayne; 06.10.2015
comment
Позвольте мне уточнить, поэтому Python не реализует публичные или частные атрибуты, потому что это притворство безопасности и побуждает программистов нести ответственность, однако сообщество поощряет использование _ для обозначения частных переменных и методов? Может быть, у python определенно должно быть публичное и частное нет? Их основная цель - рассказать вам, какой API вы должны использовать для взаимодействия с классом. Они служат в качестве документации, говорящей вам использовать эти методы, а не использовать их. Они не являются претензией на безопасность, это документация по API, которую даже IDE может использовать в качестве руководства! - person PedroD; 15.10.2015
comment
Python действительно имеет общедоступные, полуобщественные и частные переменные: foo, _foo и __foo. IDE и другие инструменты поддерживают их и вызывают внешние ссылки на внутренние компоненты класса. Но опять же, это не требует соблюдения этого: если вы полны решимости сбежать из песочницы, что ж, продолжайте, но ответственность за то, чтобы не сломать материал, лежит на вас. - person Kirk Strauser; 15.10.2015
comment
Что-то, о чем, кажется, еще не упоминалось конкретно, - это видимость, которая упрощает отладку: если у вас есть проблема, и этот метод или переменная выходит за рамки некоторого кода, вы знаете, что этот код не вызвал функцию, которая применяет ошибочное значение к некоторой переменной или напрямую, но ошибочно, изменяет переменную. С '__' в Python вы не можете этого гарантировать, но это становится менее вероятным. На других языках (Java, C ++) это, безусловно, полезно (даже если вызывает недоумение у разработчиков, которые хотят добавлять / изменять функции). - person MrMas; 19.11.2015
comment
@ Вездесущий: да, можно. В Java есть API отражения: tutorials.jenkov.com/java- отражение / Приватный - термин, вводящий в заблуждение, когда речь идет об уровнях доступа. Это больше похоже на спрятанное под капотом. Кто угодно может открыть капот, но большинство людей не должны. - person Arnab Datta; 08.01.2016
comment
Ларри Уолл прекрасно выразил культурную идею (для Perl, на странице руководства perlmod 5.0): Perl не увлечен принудительной конфиденциальностью. Он предпочел бы, чтобы вы не заходили в его гостиную, потому что вас не пригласили, а не потому, что у него есть дробовик. Та же идея для Python. - person Lutz Prechelt; 23.02.2016
comment
Вы защищаете его от себя. - person Saurabh; 08.04.2016
comment
Отражение - это не совсем то, что вы можете сделать случайно, и на самом деле, насколько я знаю, это единственный способ возиться с частными переменными. Удивительно, что одновременно Python побуждает нас быть ответственными программистами, говоря о том, как даже новички могут кодировать на Python! - person Aneesh Barthakur; 20.04.2016
comment
@AneeshBarthakur Вы также не можете случайно получить доступ к AnotherClass.__foo, так как вам нужно вычислить его производное имя, зависящее от реализации. В CPython 3.5 это будет выглядеть как AnotherClass._AnotherClass__foo. Конечно, это преодолимо (если вы знаете, в какой реализации будет работать ваш код!), Но это огромный предупреждающий знак, что вам не следует этого делать. - person Kirk Strauser; 20.04.2016
comment
Вы правы ... Несколько часов между моим столкновением с этой веткой и теперь немного научили меня по этому поводу! - person Aneesh Barthakur; 20.04.2016
comment
@AneeshBarthakur О, круто! Мы все вместе и учимся по ходу дела. :-) - person Kirk Strauser; 20.04.2016
comment
Это хороший ответ, и ваши рассуждения, безусловно, верны, но я не согласен с одним аспектом. Целью модификаторов доступа никогда не было безопасность. Скорее, они являются средством явного разграничения (и в значительной степени обеспечения соблюдения) того, какие части класса считаются внутренними, а какие доступны для внешних пользователей этого класса. Соглашения (культура), безусловно, являются допустимой альтернативой модификаторам доступа, и оба метода имеют свои плюсы и минусы, но неверно предполагать, что модификаторы доступа на уровне языка каким-либо образом предназначены для обеспечения безопасности в обычном смысле этого слова. - person devios1; 04.01.2017
comment
Это не "Java-способ", это "oop" или "C ++". - person Vassilis; 14.07.2017
comment
Python - это ООП, а это не способ Python, поэтому в целом это не способ ООП. - person Kirk Strauser; 14.07.2017
comment
Мы потратили годы на то, чтобы программисты были осторожны и не трогали вещи, которые им не следует трогать. Угадайте что, несчастные случаи случаются. Вот почему публичный / частный / защищенный были добавлены на многие языки. Так же, как автосигнализации (или «клуб»), они отпугивают целый класс воров, но не отъявленных воров. Их ничто не заблокирует. Цель публичного / частного - получить максимальную отдачу от вложенных средств, исключить общие классы ошибок, которые возникают случайно. - person Evvo; 12.04.2018
comment
@Evvo вы случайно не набираете начальное подчеркивание, поэтому всякий раз, когда вы набираете что-то вроде someobj._attrib, вы знаете, что нарушаете инкапсуляцию. С этого момента вы берете на себя полную ответственность за любые нежелательные последствия. - person bruno desthuilliers; 13.04.2018
comment
@Bruno - Всевозможные вещи происходят случайно, из-за людей, которые спешат, из-за людей, которые просто хотят сократить путь к другим вещам, но случайно думают, что вы печатаете в другом окне. Это цель контроля видимости, чтобы избежать подобного рода происшествий или недоразумений. Особенно при работе со сторонним программным обеспечением. Я очень долго работал разработчиком и видел все возможные «упы». Когда дело касается дисциплины и строгости, я доверяю компиляторам гораздо больше, чем людям. - person Evvo; 14.04.2018
comment
@Evvo Что ж, я работаю профессиональным программистом более 20 лет и сам видел немало ошибок, и я определенно НЕ доверяю компиляторам - я бы предпочел доверять хорошему линтеру и хорошему покрытию unitttest. Невозможно создать защищенный от идиотов язык - и Java, и Ada потерпели неудачу в этом (довольно эпично для Ada) - поэтому давайте не будем обманываться, думая, что если он компилируется, то он правильный. - person bruno desthuilliers; 16.04.2018
comment
Я получил ответ на то, что искал - в Python нет модификаторов доступа, но есть хаки, чтобы сделать их почти закрытыми. Однако этот ответ пахнет своего рода высокомерием, пытающимся унизить Java / C ++ (и любые другие языки, в которых есть эти модификаторы). Как давний Java-разработчик, решивший попробовать Python для развлечения, этот ответ определенно деморализует :-( - person Saurabh Srivastava; 11.06.2018
comment
Привет, @SaurabhSrivastava! Это не было деморализующим или снисходительным. Я улыбался, когда писал это десять лет назад, и улыбаюсь сегодня. Добро пожаловать в мир веселья! - person Kirk Strauser; 12.06.2018
comment
Стоит отметить, что частное и публичное на самом деле не о безопасности. Если у плохого парня есть доступ к вашим материалам через код, значит, он уже принадлежит вам. Это больше касается гигиены кода, принудительной инкапсуляции и предоставления компилятору информации о том, следует ли выполнять компиляцию в дешевые локальные вызовы или несколько более дорогие вызовы методов. Все, что не входит в контракт, вы делаете закрытым, поэтому, когда ваш класс вызывает себя через эти частные вызовы, компилятор может генерировать для них более быстрые вызовы в стиле C. Python доверяет вам писать гигиеничный код, и, будучи интерпретируемым языком, оптимизация компилятора не в счет. - person Shayne; 16.08.2018
comment
Когда пользователь набирает dir(SomeObject) и видит атрибут с привлекательным названием, который начинается с символа подчеркивания, есть большая вероятность, что он (или я) попытаюсь его использовать. Обычно читать, почему бы и не установить? Я не думаю, что любое количество подчеркиваний естественно или явно делает что-либо частным в традиционном смысле (а очевидность - обычно лучшее в Python). Было бы неплохо, если бы они не появлялись в dir() или help() и т. Д., Это сделало бы их много более приватными. - person Demis; 01.10.2018
comment
В Python вы не пишете в экземпляры других классов или переменные класса. Но это будет означать использование функций установки (иначе вы никогда ничего не сможете установить), что считается непифоническим. Разве поэтому не нормально записывать переменные класса, если они не называются частными? - person Vic; 13.05.2019
comment
Я удивлен, что тех, кто хочет внедрить вредоносный код, больше не обсуждают. Это реальный вопрос: нет ли в Python способа предотвратить доступ хакера-хакера к вашим переменным и методам и вставку кода / данных, которые могут отказать в обслуживании, раскрыть личную (или проприетарную) информацию? Если Python не позволяет использовать этот тип безопасности, следует ли его когда-либо использовать для конфиденциальных данных? Я собираюсь исследовать, задавал ли кто-нибудь этот вопрос, потому что я собираюсь задать его, если никто не задавал. - person bballdave025; 20.08.2019
comment
@ bballdave025 Учитывая, что Python поставляется в виде исходного кода, любые хакеры могут буквально просто редактировать код сами. Те же самые хакеры могут модифицировать файл .jar для запуска своего собственного кода, если на то пошло. Я лично могу поручиться, что Python используется для обработки большого количества конфиденциальных данных. - person Kirk Strauser; 20.08.2019
comment
@Kirl_Strauser, вы заставили меня чувствовать себя в большей безопасности при использовании Python с конфиденциальными данными - как благодаря вашему объяснению, так и вашим личным поручениям. Он завершает то, что я узнал из этого ответа на мой вопрос. - person bballdave025; 13.12.2019
comment
Это очень лицемерный ответ. В то же время вы утверждаете, что язык отбрасывает видимость безопасности из соображений ответственности, вы также говорите, что существует соглашение о том, что вы не хотите, чтобы люди трогали ваш код, что усиливает важность инкапсуляции. - person Leonardo Raele; 27.01.2020
comment
@LeonardoRaele Я думаю, ты не очень хорошо это понял. Более десяти лет назад я написал, что Python не рассматривает такие вещи, как пуленепробиваемые контракты. То же самое и с типизацией: хотя вы можете сказать, что функция работает с целыми числами, вы можете передать строку, если действительно хотите злоупотребить системой. Поэтому вместо жестких линий на песке подход Python состоит в том, чтобы задокументировать, как вы должны использовать систему, но не очень стараться помешать вам сделать обратное, если это действительно необходимо. - person Kirk Strauser; 27.01.2020
comment
Основная причина уровней доступа в классе - изолировать внутренний бизнес, а не безопасность. Представьте, что вы используете сторонний класс и передаете переменную, которая используется внутри этого класса и может быть изменена в любое время без какого-либо уведомления! Когда язык не поддерживает закрытые члены, вы даже не можете различить внутренние переменные назначения. - person Rman; 02.03.2020
comment
@Rman К счастью, Python различает публичные и частные переменные. Как объяснялось, вы можете получить доступ к частному атрибуту, если вам это абсолютно необходимо, но Python не облегчает вам задачу. - person Kirk Strauser; 02.03.2020
comment
Я не вешаю замки на свои двери, потому что это всего лишь видимость безопасности. Вместо этого я призываю общественность проявить ответственность. - person loweryjk; 29.10.2020
comment
@ArnabDatta в хорошей ссылке, которую вы разместили о доступе к закрытым полям и методам в Java, говорит автор. Примечание. Это работает только при запуске кода в качестве автономного приложения Java, как вы это делаете с модульными тестами и обычными приложениями. Если вы попытаетесь сделать это внутри Java-апплета, вам придется повозиться с SecurityManager. Есть ли что-то вроде диспетчера безопасности в Python, которое предотвратило бы доступ к переменной dunderscore в контексте приложения / API и т. Д.? - person JacoSolari; 14.06.2021

Частные переменные в Python - это более или менее хакерство: интерпретатор намеренно переименовывает переменную.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

Теперь, если вы попытаетесь получить доступ к __var вне определения класса, это не удастся:

>>> x = A()
>>> x.__var # this will return error: "A has no attribute __var"

>>> x.printVar() # this gives back 123

Но вы легко можете обойтись без этого:

>>> x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

>>> x._A__var = 456 # you now know the masked name of private variables
>>> x.printVar() # this gives back 456

Вы, наверное, знаете, что методы в ООП вызываются следующим образом: x.printVar() => A.printVar(x), если A.printVar() может получить доступ к какому-либо полю в x, это поле также может быть доступно вне _8 _... в конце концов, функции создаются для повторного использования, внутри высказываний нет особой силы.

Игра отличается, когда задействован компилятор (конфиденциальность - это концепция уровня компилятора). Он знает об определении класса с модификаторами контроля доступа, поэтому может выдать ошибку, если правила не соблюдаются во время компиляции.

person watashiSHUN    schedule 26.09.2015
comment
короче это не инкапсуляция - person watashiSHUN; 27.09.2015
comment
Интересно, есть ли у PHP что-то подобное с его тупыми частными переменными - поскольку частные переменные действительно не имеют смысла в интерпретируемом языке - я имею в виду, какую оптимизацию он может делать, зная, что переменная x является частной, если она не скомпилирована? - person NoBugs; 24.12.2015
comment
Как мы можем рандомизировать паттерн частных переменных? - person crisron; 07.02.2016
comment
@crisron тот же вопрос - person IanS; 17.02.2016
comment
Использование self.__dic__ = {} запрещает использование метода __str__. Есть ли способ использовать __str__ в этом контексте? - person arsho; 19.05.2017
comment
На самом деле это не работает. Вот ошибка: AttributeError: 'A' object has no attribute '_A__var1' Код: gist.github.com/arsho/98db85456f57b92639faedcf7aff045a - person arsho; 19.05.2017
comment
@arsho ты абсолютно прав, попробую обновить, если найду лучшее решение - person watashiSHUN; 19.05.2017
comment
@crisron, вам нужно использовать дескриптор, вот пример переименования атрибутов - person watashiSHUN; 26.05.2017
comment
@watashiSHUN короче, это не инкапсуляция = ›да, это так. Инкапсуляция - это только использование общедоступного API, поэтому клиентский код защищен от изменений реализации. Соглашения об именах - это совершенно верный способ рассказать, что такое API, а что реализация, и дело в том, что он просто работает. - person bruno desthuilliers; 13.04.2018
comment
Инкапсуляция не имеет ничего общего с тем, можете ли вы получить доступ к частной переменной с помощью запутанных методов. Любой желающий может получить доступ к памяти непосредственно в C ++, в которой есть частные переменные. Python также может обращаться к частным переменным. Подумаешь. - person Mateen Ulhaq; 24.10.2018
comment
С другой стороны, если вы предоставляете методы get и set для частных полей, вы можете смело утверждать, что эти не инкапсулированы! Итак, очевидно, что инкапсуляция - это проблема дизайна, а не языковых функций. - person Mateen Ulhaq; 24.10.2018

Как правильно упоминалось во многих комментариях выше, давайте не будем забывать о главной цели модификаторов доступа: помочь пользователям кода понять, что должно измениться, а что не должно. Когда вы видите частное поле, вы не возитесь с ним. Так что это в основном синтаксический сахар, который легко достигается в Python с помощью _ и __.

person Ardavan    schedule 17.11.2014
comment
Я считаю, что это не менее важный момент. При отладке кода (я знаю, что я слабак, чтобы вносить ошибки), знание того, какие классы могут изменять переменную-член, упрощает процесс отладки. По крайней мере, если переменная защищена какой-то областью видимости. Похожая концепция - это константные функции в C ++. Я знаю, что переменные-члены не были изменены, поэтому я даже не рассматриваю этот метод как потенциальную причину неправильной настройки переменной. Хотя это может сделать последующую разработку расширений классов / добавление функций, ограничение видимости кода упрощает отладку. - person MrMas; 19.11.2015

В соглашении о подчеркивании существует разновидность частных переменных.

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

Есть некоторые тонкие различия, но для идеологической чистоты программного шаблона их достаточно.

Есть примеры декораторов @private, которые более точно реализуют эту концепцию, но YMMV. Возможно, можно было бы также написать определение класса, использующее мета

person Shayne    schedule 02.09.2014
comment
Я понимаю, что это довольно поздно для вечеринки, но эта ссылка появляется в Google при поиске проблемы. Это не говорит всей истории. __x как переменная внутри класса A фактически переписывается компилятором в _A__x, она все еще не полностью закрыта и все еще доступна. - person Zorf; 14.10.2014
comment
Конечно, если я увижу переменную с именем _A__x, я не буду ее трогать. Это могло быть заразно. Я убегу от этого к черту. - person Mateen Ulhaq; 09.01.2017
comment
ПРАВИЛЬНО уверен, что это не истинный частный. Но основная аргументация в пользу жесткого принудительного частного в C ++ и Java (и т.д.), оптимизации компилятора, на самом деле не существует в Python, поэтому частное по соглашению достаточно хорошо. Соглашение Python обычно заключается в том, что он полагает, что вы будете вести себя без присмотра. (И это ловушка для новичков, но вы знаете, просто подумайте о дизайне классов и потреблении) - person Shayne; 20.08.2019

Как упоминалось ранее, вы можете указать, что переменная или метод являются закрытыми, поставив перед ними знак подчеркивания. Если вам кажется, что этого недостаточно, вы всегда можете использовать декоратор property. Вот пример:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

Таким образом, кто-то или что-то, что ссылается на bar, на самом деле ссылается на возвращаемое значение функции bar, а не на саму переменную, и поэтому к нему можно получить доступ, но нельзя изменить. Однако, если кто-то действительно этого хочет, он может просто использовать _bar и присвоить ему новое значение. Как уже неоднократно говорилось, нет надежного способа предотвратить доступ кого-либо к переменным и методам, которые вы хотите скрыть. Однако использование property - это самое ясное сообщение, которое вы можете отправить, что переменная не подлежит редактированию. property также можно использовать для более сложных путей доступа для получения / установки / удаления, как описано здесь: https://docs.python.org/3/library/functions.html#property

person Isaac Saffold    schedule 14.04.2017
comment
Джанго тоже это ценит. - person babygame0ver; 09.02.2019

«В java нас учили общедоступным / частным / защищенным переменным»

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

По той же причине это не требуется в Java.

Вы можете использовать - или не использовать private и protected.

Как программист на Python и Java, я обнаружил, что private и protected - очень, очень важные концепции дизайна. Но на практике в десятках тысяч строк Java и Python я никогда на самом деле не использовал private или protected.

Почему нет?

Вот мой вопрос "защищен от кого?"

Другие программисты в моей команде? У них есть источник. Что значит защищенный, когда они могут это изменить?

Другие программисты в других командах? Они работают в одной компании. Они могут - с помощью телефонного звонка - получить источник.

Клиенты? Это программирование по найму (как правило). Клиенты (как правило) владеют кодом.

Итак, от кого - именно - я защищаю его?

person S.Lott    schedule 29.10.2009
comment
@Omnipresent: я не знаю о крыльях, но я знаю, что - из-за Java - я не особо использую утиную печать. Если бы я это сделал, я мог бы работать на Python еще более продуктивно. Я считаю, что хорошая иерархия наследования (та, которая была бы переведена на Java) обычно стоит усилий в Python. - person S.Lott; 29.10.2009
comment
@Porculus: чтобы ваша IDE могла легко узнать ... Что? Моя IDE - редактор. Я дизайнер. Я знаю, что это за дизайн. Моя IDE - редактор и ничего не знает. Кто такой таинственный никто, случайно воспользовавшийся чем-то еще? Конкретно? Кто это? Почему им не сообщают, как правильно использовать API? - person S.Lott; 23.07.2010
comment
-1: Я согласен с Поркулусом. Речь идет не о запрете доступа или сокрытии чего-либо, а о неявной документации API. Разработчики, а также компиляторы / интерпретаторы / средства проверки кода легко видят, какие члены рекомендуется использовать, а какие не следует трогать (или, по крайней мере, с осторожностью). В большинстве случаев было бы ужасным беспорядком, если бы все члены класса или модуля были общедоступными. Рассмотрим различие между частными / защищенными / общедоступными членами как услугой, сказав: «Эй, эти члены важны, в то время как они используются внутри компании и, вероятно, бесполезны для вас». - person Oben Sonne; 07.10.2010
comment
@Oben Sonne: Неявная документация по API? Какие? Вы имеете в виду, позволяя людям догадываться, в чем заключаются ваши намерения? Как можно догадаться? Общедоступный / частный / защищенный кажется очень плохим по сравнению с реальной документацией, написанной для поддержки реальных сценариев использования программиста. - person S.Lott; 07.10.2010
comment
@ S.Lott: Я согласен с тем, что документы API имеют более высокий приоритет и часто являются единственным способом сообщить о предполагаемом использовании API. Но иногда имена и видимость участников (с точки зрения частного / общедоступного) говорят сами по себе. Кроме того, я понимаю вашу точку зрения, что идея неявной документации не работает в редакторах без проверки API, но действительно помогает в IDE с автозавершением кода. Предполагая, что вы уже читали документацию по API некоторое время назад, это поможет вам вспомнить, как использовать класс. Все не работало бы так умно, если бы не было различия между частными и общедоступными участниками. - person Oben Sonne; 15.10.2010
comment
@ Обен Сонне: Все не работало бы так умно, если бы не было различия между частными и публичными участниками? Вещи? Какие вещи? IDE с автозавершением кода? Разве это не сработает с умом? Прочтите amazon.com/Large-Scale-Software-Design- Джон-Лакос / dp / 0201633620. Общедоступный / частный / защищенный объединяют слишком много вещей, чтобы быть действительно полезным. Документация по API часто содержит все больше и больше полезной информации, которая private. private - это просто слишком мало информации, чтобы иметь какую-либо реальную ценность. - person S.Lott; 15.10.2010
comment
Поздно до обсуждения, но все, что здесь запрашивают Поркулус и Обен, совершенно адекватно обрабатывается префиксом it с соглашением о подчеркивании (и без вреда, который может причинить соблюдение этого соглашения компилятором) - person ncoghlan; 02.03.2011
comment
@ncoghlan Какой вред наносит принудительное применение компилятора? - person hiwaylon; 20.02.2012
comment
@everybody else См. Gamma, E., et al., Design Patterns (1995), p11 и p13. - person hiwaylon; 20.02.2012
comment
@hiwaylon: Абсолютно верно. Полностью согласен. Инкапсуляция - это конструктивная особенность. Конфиденциальность не помогает сделать дизайн инкапсулированным. Он обеспечивает только поддержку компилятора, чтобы люди не могли использовать атрибуты, которых они не должны. Программирование интерфейса - это вопрос наличия определенного интерфейса и его документирования. Private - это просто поддержка компилятора, чтобы помочь людям, которые не могут читать документацию или отказываются следовать ей. - person S.Lott; 20.02.2012
comment
@hiwaylon Инкапсуляция по соглашению означает, что вы можете прервать инкапсуляцию, если у вас есть веская причина (например, введение дополнительного журнала для поиска источника плохих обновлений состояния приложения). С принудительным исполнением на уровне компилятора вы просто не можете делать много вещей, которые очень полезны при поддержке и тестировании реального программного обеспечения (посмотрите на шаблоны проектирования для Java и C ++: многие из них посвящены написанию большого количества дополнительного кода, чтобы дать у вас есть дополнительные точки расширения). - person ncoghlan; 23.02.2012
comment
@hiwaylon Это подход взрослых к разработке API, основанный на согласии взрослых - подчеркивание говорит о том, что вы сами по себе, если начнете возиться с этим, но язык не остановит вас, если вы сочтете это необходимым. Принуждение, с другой стороны, ставит исходного разработчика API в положение, когда он говорит, что вы не должны использовать мой API способами, которые я не планировал заранее. Даже если вы готовы принять на себя связанный с этим риск, компилятор вам просто не позволит. - person ncoghlan; 23.02.2012
comment
@ncoghlan Об этом говорится в Интернете и в многочисленных публикациях Python. Не делает их священным писанием. Применение компилятором интерфейса, строгая инкапсуляция данных и типизация многими считаются большими преимуществами. Конфиденциальность не помогает сделать дизайн инкапсулированным. Согласитесь не согласиться. Private - это просто ... чтобы помочь людям, которые не могут читать документацию или отказываются следовать ей. Опять глупо. Как мы все можем согласиться, есть преимущества как в языках высокого уровня со слабой типизацией, так и в языках со строгой типизацией низкого уровня. Все они инструменты в наборе инструментов! - person hiwaylon; 25.02.2012
comment
@hiwaylon: Если вы настаиваете на объединении инкапсуляции - техники проектирования - с конфиденциальностью - техники реализации - я могу понять, почему вы утверждаете, что конфиденциальность имеет магическое значение. Представьте программиста на C ++, который просто не использует private. Вы хотите сказать, что хорошо инкапсулированный, хороший дизайн по волшебству не может показать хорошую инкапсуляцию из-за отказа от использования private? Если это так, тогда friend объявления, которые выборочно удаляют конфиденциальность, сделают дизайн волшебным образом не инкапсулированным. Даже если хорошо контролировать? Я вообще не покупаю private == хорошее. - person S.Lott; 25.02.2012
comment
Прямой доступ к общедоступным данным является нарушением инкапсуляции. Хотя соглашение о подчеркивании помогает выразить намерение, наличие ключевого слова private в языке, безусловно, неплохо. - person hiwaylon; 27.08.2012
comment
Не могли бы мы эффективно реализовать частные, общедоступные, защищенные умными метаклассами? - person gerrit; 21.03.2013
comment
@ S.Lott - Хотя я частично согласен, в Java исключение _1 _ / _ 2_ НЕ означает, что происходит. Он обеспечивает видимость элемента по умолчанию, что означает, что он виден внутри своего пакета, но не откуда-либо еще (включая подпакеты). Вы действительно должны использовать видимость для функциональности в большинстве случаев. - person Qix - MONICA WAS MISTREATED; 09.07.2013
comment
Раньше я думал, что private public - это немного глупо, но после правильного использования классов, где у вас может быть значительное количество очень маленьких функций в классе, вы хотите иметь возможность добавлять методы, которые предназначены только для использования из другие методы в этом классе. Дело в том, что если вы знаете, что этот метод будет иметь смысл только для вызова из другого метода в том же классе, тогда сделайте его частным, и вы не будете думать об этом, если вы находитесь вне его. - person Chris Barry; 25.08.2013
comment
@ S.Lott Я не любитель питонов, поэтому не буду комментировать с этой точки зрения. Однако для разработчика java это поистине ужасающий совет. -1 - person dbyrne; 06.06.2014
comment
Может, защититься от моих глупых ошибок? Я согласен с мнением, что модификаторы доступа помогают вам разобраться в коде. Они предоставляют уведомление во время компиляции о том, что ожидается от человека, написавшего библиотеку (при условии, что он знал, что делал). Я люблю Python, но говорить, что вы никогда не использовали private или protected за всю свою карьеру, кажется чрезмерно упрямым. В отсутствие культурных соглашений, как в Python, имеет смысл сообщить компилятору о своих намерениях. На большинстве языков, которые их поддерживают, другие ожидают, что вы будете использовать их, чтобы сообщить о своих намерениях. - person jpmc26; 02.07.2014
comment
Разве не все дело в принуждении? В Java компилятор реализует намерение автора. В Python отсутствие работающей программы указывает на то, что интерпретатор Python применяет намерение записи. OTOH, использование класса Java во время выполнения неправильно указывает на то, что кто-то не читал документацию или не понимал дизайн. В Python это означает то же самое. Это зависит от того, что вы хотите использовать другим кодировщикам и как вы хотите, чтобы они узнали, как это использовать. Все использовали бы документацию. Java заставит вас читать во время компиляции (или после). Python, когда программа взрывается. - person johnny; 29.12.2014
comment
Согласен с С.Лоттом. Если вся точка является неявным указанием на использование, Python решает ее с помощью префикса подчеркивания, а поскольку другой точки нет, как мы пришли к выводу, частный / общедоступный Java является ненужным осложнением. - person Aaron Hall; 06.02.2015
comment
Частные и защищенные переменные обеспечивают соблюдение надлежащих методов проектирования. Все мы люди, и все мы временами чувствуем себя ленивыми или уставшими. Многие люди не могут заставить себя бросить курить или начать заниматься спортом, даже если они знают, что для них лучше. Точно так же у многих людей возникнет соблазн использовать частные переменные, если для этого нет таких препятствий. Объявить что-то личное - значит взять на себя обязательство, которое вы собираетесь выполнить. Преимущество состоит в том, что вы можете почти идеально инкапсулировать фрагмент кода, отшлифовать его и чувствовать себя в безопасности. Такой безопасности никогда не бывает в Python. - person Sergey Orshanskiy; 14.04.2015
comment
Не согласен, это улучшает читаемость и помогает другим программистам узнать, какой метод следует использовать или нет, даже если они могут измениться. - person Sing; 13.01.2017
comment
Вот это да. Вы полностью упускаете суть, даете очень плохой совет, оскорбляете любого, кто не согласен с вами по этому поводу, но вы все равно получаете значки и более 1000 очков репутации за этот ответ. - person Eric Duminil; 19.01.2017
comment
+1 Но, наконец, @ S.Lott опубликовал около 2500 сообщений и заработал около 20000 репутаций на теге «python». Язык - это всего лишь язык, в нем могут быть некоторые моменты, с которыми вы не будете соглашаться вечно, но имеет ли значение быть хорошим программистом? Ответ очевиден. - person Rainning; 23.04.2018
comment
Не говоря уже о шаблонах проектирования, которые он также заработал много значков на сайте Software Engineering SE. - person Rainning; 23.04.2018
comment
Ладно, твоя точка зрения на protected - демагогия, но ладно. Так что насчет private? Интрига! Станет ли private в вашей трактовке солдатом низшего звания? Или вы будете утверждать, что программист будет вынужден владеть var / method, но вы коммунист и против частной собственности (каламбур непреднамеренно) на средства производства (а vars / методы, очевидно, являются средствами производства)? - person jungle_mole; 15.08.2019
comment
Я работал с клиентами, которые обрабатывают конфиденциальную и личную информацию. Для меня частные и защищенные ключевые слова были важны для предотвращения злонамеренного внедрения хакерами в черные шляпы кода или данных в открытые методы. Судя по тому, что я читаю - и я буду счастлив, если кто-то скажет мне, что я неправильно это понимаю - Python не позволяет вам помешать кому-либо со злым умыслом получить доступ к вашей конфиденциальной информации. Кажется, что переменные и функции класса и экземпляра действительно не имеют хорошего метода защиты. (продолжение следует...) - person bballdave025; 20.08.2019
comment
(... продолжение) Q: защищен от кого? A: от злонамеренных хакеров в черной шляпе - доступ к переменным и функциям - ›отказ в обслуживании, доступ к конфиденциальной информации ... Кажется, подход A._no_touch = 5 заставит такого злонамеренного кодировщика посмеяться над моим, пожалуйста, не трогайте это. Мой A.__get_SSN(self) кажется просто желаемым, надеясь, что черная шляпа не знает трюка Зорфа. Я хочу, чтобы мне сказали, что я полностью скучаю по вещам. Не следует ли кодировать конфиденциальную информацию на Python? Я правда не знаю, но хочу знать. - person bballdave025; 20.08.2019
comment
Стоит отметить, что в скомпилированных языках Private / Public на самом деле влияют на производительность, поскольку они определяют, следует ли маршрутизировать вызовы напрямую (то есть частный самостоятельный вызов) или через косвенный вызов таблицы вызовов (поиск метода в чужом классе, возможно, занимая несколько кругов иерархия классов, а затем вызывая его) - person Shayne; 20.08.2019
comment
@ bballdave025 Уровни защиты не о безопасности. Уверяю вас, если у черной шляпы есть доступ к памяти, ни ад, ни высокая вода не скроют от него свойства класса. Речь идет о документировании для кодировщика (и компилятора!) Аудитории метода .. Это для внутреннего использования в классе или «опубликовано» для использования другими классами. Если вам нужны безопасные поля, это тема, выходящая за рамки видимости методов и свойств. - person Shayne; 20.08.2019
comment
@Shayne, это простое заявление, но оно помогает мне понять, в чем я схожу с курса. Если я понимаю, о чем вы говорите, public, private, protected и подчеркивания не нужны для компьютерной безопасности, они позволяют тем, кто будет работать с вашим кодом, знать, что принадлежит к какому классу. Звучит правильно? Я всегда думал, что эти ключевые слова касаются компьютерной безопасности. Приятно узнать их реальное применение. - person bballdave025; 20.08.2019
comment
Никакие Public, Protected и Private не имеют абсолютно ничего общего с безопасностью. Они об аудитории для элементов контракта на занятия. Если вы полагаетесь на них в плане безопасности, я боюсь, что вам придется пережить тяжелые времена. Компилятор абсолютно ничего не делает, чтобы защитить их от злоумышленников, потому что эти языковые функции просто не для этого. - person Shayne; 20.08.2019
comment
Спасибо. К счастью, я не работаю в службе безопасности. Я физик, который научился программировать, особенно в аспирантуре, полюбил это и занялся исследованиями и разработками в компьютерном мире. Мне всегда нравится заполнять пробелы, оставленные моим образованием. Спасибо, что нашли время мне это объяснить. - person bballdave025; 20.08.2019
comment
Нет проблем, приятель, вот для чего SO :) - person Shayne; 20.08.2019

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 и __- instance.

Если у вас есть открытые общедоступные переменные и вам необходимо их инкапсулировать, вы можете использовать @property. Поэтому вы можете начать с самого простого из возможных решений. Вы можете оставить переменные-члены общедоступными, если у вас нет конкретной причины этого не делать. Вот пример:

class Distance:
    def __init__(self, meter):
        self.meter = meter


d = Distance(1.0)
print(d.meter)
# prints 1.0

class Distance:
    def __init__(self, meter):
        # Customer request: Distances must be stored in millimeters.
        # Public available internals must be changed.
        # This would break client code in C++.
        # This is why you never expose public variables in C++ or Java.
        # However, this is python.
        self.millimeter = meter * 1000

    # In python we have @property to the rescue.
    @property
    def meter(self):
        return self.millimeter *0.001

    @meter.setter
    def meter(self, value):
        self.millimeter = meter * 1000

d = Distance(1.0)
print(d.meter)
# prints 1.0
person Hatatister    schedule 26.06.2018
comment
Я собираюсь проверить этот разговор. Является ли эта @property частью стандартного Python или она специфична для IDE? - person bballdave025; 20.08.2019
comment
Это часть стандарта, начиная с Python 2.6. Если вы должны использовать старую версию, все еще есть возможность использовать встроенную функцию property, которая доступна с python 2.2. - person Hatatister; 21.08.2019

Python имеет ограниченную поддержку частных идентификаторов благодаря функции, которая автоматически добавляет имя класса к любым идентификаторам, начинающимся с двух знаков подчеркивания. По большей части это прозрачно для программиста, но в конечном итоге любые переменные, названные таким образом, могут использоваться как частные переменные.

Дополнительную информацию см. здесь.

В целом реализация объектной ориентации в Python несколько примитивна по сравнению с другими языками. Но на самом деле мне это нравится. Это очень простая в концептуальном плане реализация, которая хорошо вписывается в динамический стиль языка.

person Dan Olson    schedule 29.10.2009
comment
Ага. Прелесть в том, что возможности метапрограммирования python означают, что вы действительно можете реализовать причудливые вещи, если хотите (и есть библиотеки, которые реализуют декораторы @ private / @ protected / etc и прочее. Черт, я даже видел библиотеку, которая реализовывала классы прототипов стиля JS по какой-то чертовой разумной причине), но на практике это просто не так необходимо ... Я как бы ненавижу python / js / независимо от того, что является шепелявым мемом, потому что это почти никогда не бывает правдой, но python действительно разделяет `` отбивные метапрограммирования в сочетании с простым синтаксисом '' с этот язык - person Shayne; 20.08.2019

Единственный раз, когда я использую частные переменные, - это когда мне нужно делать другие вещи при записи или чтении из переменной, и поэтому мне нужно принудительно использовать сеттер и / или геттер.

Как уже говорилось, это снова относится к культуре. Я работал над проектами, в которых чтение и запись переменных других классов было бесплатным для всех. Когда одна реализация стала устаревшей, потребовалось гораздо больше времени, чтобы идентифицировать все пути кода, в которых использовалась эта функция. Когда использование методов установки и получения было принудительным, можно было легко написать оператор отладки, чтобы определить, что был вызван устаревший метод, и путь кода, который его вызывает.

Когда вы работаете в проекте, где любой может написать расширение, уведомление пользователей об устаревших методах, которые должны исчезнуть в нескольких выпусках, поэтому жизненно важно для минимизации поломки модуля при обновлении.

Итак, мой ответ; если вы и ваши коллеги поддерживаете простой кодовый набор, защита переменных класса не всегда необходима. Если вы пишете расширяемую систему, то становится необходимым, когда в ядро ​​вносятся изменения, которые должны быть перехвачены всеми расширениями, использующими код.

person BlueEagle    schedule 28.04.2013

Извините, ребята, что "воскресили" ветку, но я надеюсь, что это кому-то поможет:

В Python3, если вы просто хотите «инкапсулировать» атрибуты класса, как в Java, вы можете сделать то же самое, например:

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

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

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

Чтобы создать это, выполните:

ss = Simple("lol")
ss.show()

Обратите внимание: print(ss.__s) выдаст ошибку.

На практике Python3 скрывает имя глобального атрибута. Сделайте это как "частный" атрибут, как в Java. Имя атрибута по-прежнему глобальное, но недоступно, как частный атрибут в других языках.

Но не бойтесь этого. Неважно. Он тоже выполняет свою работу. ;)

person Ferrarezi    schedule 15.08.2017
comment
это существует с Python 1.5.2 IIRC, и до сих пор не препятствует доступу к атрибуту через его искаженное имя. - person bruno desthuilliers; 13.04.2018
comment
Имя атрибута не является глобальным. - person shivams; 09.02.2021

частные и защищенные концепции очень важны. Но python - всего лишь инструмент для прототипирования и быстрой разработки с ограниченными ресурсами для разработки, поэтому некоторые уровни защиты в python не так строго соблюдаются. Вы можете использовать «__» в члене класса, он работает правильно, но выглядит недостаточно хорошо - каждый доступ к такому полю содержит эти символы.

Кроме того, вы можете заметить, что концепция ООП python не идеальна, smaltalk или ruby ​​намного ближе к чистой концепции ООП. Даже C # или Java ближе.

Python - очень хороший инструмент. Но это упрощенный язык ООП. Синтаксически и концептуально упрощен. Основная цель существования Python - предоставить разработчикам возможность очень быстро писать легко читаемый код с высоким уровнем абстракции.

person user711294    schedule 17.07.2011
comment
Причина, по которой Private и Protected важны, заключается в том, что в статически компилируемых языках компилятор может создавать прямые вызовы частного метода, но должен полагаться на таблицу поиска для общедоступных методов. Это просто не проблема с динамическими языками. Наконец, такие языки, как C ++, имеют значение для наследования и разрешения методов. Python и Ruby имеют очень похожие реализации объектно-ориентированного программирования, поэтому сравнение бессмысленно. Smalltalk фактически не имеет понятия об общедоступных / частных сообщениях. Вы можете добавлять частные в категорию бесплатно, но это чисто рекомендательный характер. - person Shayne; 24.02.2017
comment
В продолжение моего утверждения. С точки зрения гигиены, да, они важны для инкапсуляции, но для нее это не необходимо, поэтому декораторы @private (etc) более рекомендательны, чем что-либо, но как частные / общедоступные не добавляет ничего полезного для оптимизации на нестатическом языке, это не реализовано на глубоком уровне, как это было бы на скомпилированном языке, таком как java или c - person Shayne; 27.02.2017

Об источниках (для изменения прав доступа и, таким образом, обхода языковой инкапсуляции, такой как java или C ++): у вас не всегда есть источники, и ДАЖЕ, если они есть, источники управляются системой, которая позволяет только определенным программистам получить доступ к источник (в профессиональном контексте). Часто каждый программист отвечает за определенные классы и поэтому знает, что он может, а что не может. Менеджер исходного кода также блокирует изменяемые источники и, конечно же, управляет правами доступа программистов.

Так что, как показывает опыт, я больше доверяю программам, чем людям. Так что соглашение - это хорошо, но МНОЖЕСТВЕННАЯ защита лучше, например, управление доступом (настоящая частная переменная) + управление источниками.

person Alan Allen    schedule 14.08.2020