Как стать автором
Обновить

Комментарии 20

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

В С# официальный кодстайл подразумевает начинать приватные свойства с нижнего подчёркивания. Это правда удобно. Однако в пайтоне это правда какой-то прикол, как и ООП в целом на пайтоне. ООП на нём не юзабелен от слова совсем.

Главного не сказали. Ваши собственные методы могут начинаться как с одного так и с двух подчёркиваний. При этом не важно, как они кончаются. Одно подчёркивание - это просто договор. Вы отмечаете, что метод приватный, но если его вызвать со стороны, то он нормально отработает без проблем. Разве что Pylance вас обматерит, и то, кажется, не по умолчанию. И это хорошо, потому что позволяет без проблем делать юниттесты а так же делать условные брейкпоинты. Я всегда говорил, что в любом языке должна быть возможность нарушать private и автоматически давать по рукам при использовании её в самом коде. Иначе код обрастает геттерами, которые нужны только для отладки.

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


Другое дело - два подчёркивания. Это попытка накостылить принудительный приват. Увидев метод, начинающийся с двух подчёркиваний, CPython вместо него добавит в имя также имя класса того места, где метод был вызван. То есть в членах того же класса оно совпадёт, а при попытке вызова из другого класса получим "метод не найден". К сожалению, есть много краевых случаев где это работает неочевидным образом, поэтому много разных людей называют эту возможность ошибкой и призывают ей не пользоваться.

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

Чем заканчиваются важно.

class Sample:
    def __my__dandr__(self):
        print("Hello World")

if __name__ == '__main__':
    Sample().__my__dandr__()

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

А можно пример таких крайних случаев?

Что‑то связанное с наследованием и исключениями, когда исключение генерируется в непереопределённом методе и обрабатывается в переопределённом. Не запоминал, потому что избегаю как name mangling так и исключений — не люблю неявное.

Вот ещё популярное видео: https://www.youtube.com/watch?v=0hrEaA3N3lk

Вот ещё популярное видео: https://www.youtube.com/watch?v=0hrEaA3N3lk

Начал смотреть и бросил.

Да, существует много людей которые Питон "выучили" сами и не знают спецификаций языка. Это вообщем проблема всех языков.

Моя рекомнедация новичкам: используйте линтеры, они съэкономят вам время. SLF001 Private member accessed: __count
Ну и коменты на хабре читать, тут многие интересные темы поднимают.

Не запоминал, потому что избегаю как name mangling так и исключений — не люблю неявное.

Нейвное, это когда что-то работает не так как выглядит. name mangling вполне явная штука, они чётко описанна в спецификации.

У name mangling единственная цель это сделать невозможными конфликты переменных при наследовании. Если вы создаёте класс для наследования или наследуетесь и не используете эту защиту, то у вас ненадёжный код. Не делайте так.

"Избегаю name mangling", звучит двусмылсенно. Я бы сказал избегать наследований это норм, а вот если уже используете наледование, то без приватных членов класса никак нельзя.

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

Программист в коде может написать все, что угодно, хоть разименовать нулевой адрес (например для написания теста). Соглашения о вызовах и именовании, это именно соглашения, и если кто-то не захотел их использовать (или не смог по другому), это не является доводом, чтобы усложнить жизнь всем остальным, заставляя их использовать перректальные механизмы доступа к приватным полям.

Возможно, это был единственный способ сделать задачу из-за общей корявой архитектуры приложения (например, нужные для наследников классов данные без геттеров и сеттеров сделали приватными, вместо защищенных)

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

Другими словами, это как ходить без одежды, следуя соглашению, что никто "туда" не смотрит. Только врач или супруг/супруга может :)

Но я не настаиваю, просто поделился опытом и мнением.

Я тоже говорю про крупные проекты и полностью разделяю ваше негодование, когда разработчик нарушает те или иные соглашения при написании кода.

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

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

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

Не очень понял насчёт возможностей работы с кодом. Если вы определили член, как приватный, вы снижаете возможности? Нет, вы защищаете свою реализацию, чтобы иметь возможность безопасно вносить изменения. Если технически возможность такая есть, значит вы рискуете кому-то испортить день, а то и не день.

Насчёт гарантий защиты. Вы дверь на ключ закрываете? А в курсе, что это не 100% гарантия защиты от проникновения? Понятно, что нет. Но это нужно приложить усилия, которые очевидным образом кричат о том, что вы делаете что-то плохое. И вам не надо даже знать о соглашениях, это очевидно.

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


В идеале ваш модуль должен быть покрыт тестами вами. А тесты на того, кто использует ваш модуль не должны вообще ваш трогать.

Тесты которые пишутся после того как кто-то начал использовать ваш код идея не очень хорошая. Они уже мало что найдут.

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

Правильно, тесты пишутся разработчиками. Но не обязательно один и тот же пишет и код и тесты. Во многих языках программирования есть такой уровень доступа к членам модуля/класса, как "дружественный". Т.е. можно определить дружественный модуль и позволить доступ к некоторым членам, обычно это как раз и применяется для тестирования.

Тестопригодность это один из показателей хорошего дизайна.

Мне очень удобно смотреть версию библиотеки, например для numpy это будет выглядеть как numpy.__version__

помню время когда было всего 640к памяти.

Я бы еще добавил что подчеркивание можно использовать для более понятной записи чисел: 10000 -> 10_000. С одной стороны мелочь. С другой стороны имхо интересно, т.к. это единственное (да?) место, где знак _ выступает не в качестве части имени объекта (переменной / метода ...)

Об этом есть в разделе "Форматирование числовых значений" :)

  • Camel case (myVariableName): Первое слово пишется в нижнем регистре, а первая буква последующих слов — в верхнем. Применяется в таких языках, как JavaScript, Java, C# и Swift.

Кажется, что здесь нуждается уточнение, и в статье ниже это затрагивается: у Python Camel case начинается с заглавной буквы.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации