По-поводу str.join() требующей итерируемое со строками — это тот самый случай из дзена — "Явное лучше неявного" и в какой-то мере "Принцип единой ответственности" (Single responsibility principle). От вас требуется явным образом привести объекты, пераданные str.join() к строке, так как Вы отвечаете за представление каждого объекта в строковом виде, а str.join() лишь за их конкатенацию.
Не соглашусь. Здесь затрагивается спецификация языка, в которой чёрным по белому написано:
...For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if it is the class or a base class of the exception object or a tuple containing an item compatible with the exception.
tuple containing an item — ключевой момент. Спецификация не допускает каких либо других контейнеров в этом месте.
Питон, пакеты и библиотеки которые требуются для работы программы. Есть также бандлеры, которые с переменным успехом собирают Питон и зависимости в единый исполняемый файл.
class NotFound:
pass
val = dict.get(key, NotFound)
if val is NotFound:
...
без проблем.
Теперь разберём ситуацию, в которой
# допустим, что вероятность key not in dict ~ 10%
val = dict.get(key, NotFound)
В синтетическом тесте, try..except может оказаться быстрее, например:
Много кода
N = 10000
P_IN = 0.90
d = dict(enumerate(range(int(N * P_IN))))
def sum_dict_in():
s = 0
for i in range(N):
s += d.get(i, 0)
return s
def sum_dict_try():
s = 0
for i in range(N):
try:
s += d[i]
except KeyError:
s += 0
return s
if __name__ == '__main__':
import timeit
print(f'Testing with {N} elements and probability of element in dictionary {P_IN}')
print(timeit.timeit("sum_dict_in()", setup="from __main__ import sum_dict_in", number=1000))
print(timeit.timeit("sum_dict_try()", setup="from __main__ import sum_dict_try", number=1000))
У меня получилось, что try..except работает быстрее вплоть до 15% промахов.
Но вся эта проблема, как мне кажется, высосана из пальца. EAFP это же не столько о скорости выполнения и о дефолтных значениях, сколько о самом принципе: не стоит погребать логику под if valid, если not valid — это исключительная ситуация.
Если бы библиотеки Питона писались только на самом Питоне, то тогда бы подобных проблем было бы меньше. А теперь представьте, что вам нужна нативное расширение, например PIL/Pillow для обработки изображений? Есть два варианта — либо вы скачиваете кем-то скомпилированное и упаковонное расширение под вашу платформу и вашу версию Питона, либо скачиваете исходники и компилируете его сами! pip может сделать и то и другое, но для компиляции ему нужен собственно компилятор, заголовочные файлы Питона, исходники или бинарники зависимостей и т.д.
npm пришёл из экосистемы, где всё пишется на JS. А в Питоне, помимо пакетов с "чистым" Питоном есть расширения, которые могут быть написаны на C/C++ и т.д. Отсюда и разница.
Спасибо за комментарий. Действительно написал двумысленно: хотел сказать, что разработчикам CPython и собственно самому CPython проще с гарантией выполнения байткода одним потоком. Подправил в тексте.
Ну вот опять… После такого «введения», желание познакомится с питоном пропадёт на веки вечные. Автор, вам самому бы не мешалось пройтись по официальному туториалу, перед тем как какие-либо руководства писать.
Эх, жалко. Последний приобретённый аппарат — как раз XZ1 compact. С фирменным прямоугольным дизайном и возможностью управлять одним пальцем. С миниджеком и защитой IP68. Со слотом расширения под microSD… можно долго перечислять и спорить о достоинствах и недостатках, но с одним не поспоришь — у Sony был свой стиль. Жалко, что его больше не будет.
В начале, хочу похвалить. Получилась интересная статья — в качестве исследования возможностей языка. Но в продакшн я бы ничего из предложенного брать не стал. И вот почему:
Вас как видимо смутило, что в Python, которому через пару лет третий десяток стукнет, до сих пор нет реализации модификаторов доступа и интерйфесов в том виде, каком они сделаны в Java / C#.
И дело даже не в договорённости на уровне языка и его культуры.
Попытавшись вызвать метод start_engine за пределами класса, вы получите следующую ошибку (метод недоступен согласно политике доступа)
ОПА! А что нам даёт эта ошибка во время рантайма? В Java / C# это будет ошибка времени компиляции, а не выполнения.
С другой стороны тот же pylint спокойно отловит доступ к private/protected методам.
А с третьей — pylint тут и не нужен. Если программист по какой-либо причине использует приватные поля базового класса, или объекта — он должен полностью отдавать себе отчёт в том, что делает.
@implements(HumanInterface)
А как же утиная типизация? Есть у объекта метод __iter__ — значит по нему (скорее всего) можно итерироваться тем же for, нету — нельзя.
Чтобы не забыли? — вот тут соглашусь, это может быть удобно в больших проекта, но…
Pylint опять спешит на помощь и ловит неимплементированные методы абстракных классов!
@throws(HumanDoesNotExistError)
— a наколько глубока интроспекция? Может где-то в глубине метода я вызываю функции, которые эти исключения бросают? А может где-то вылетают и другие исключения?
Всё вышепредложенное, в Питоне есть на уровне устоявшихся конвенций или может быть реализовано на уровне программ статического анализа кода.
Как-будто вернулся в конец 90-х и прочёл статью из свежего, пахнущего типографской краской «Хакера». С заголовком «Ё-мыло: скрываем почту с помощью PHP»
Ага, семья моей прабабушки — крестьяне со своим хозяйством, крымские немцы, бежали из Крыма в Тбилиси, а потом — в Баку. И это лишь благодаря человеку который «случайно» обронил фразу «За вами завтра придут. Бегите!». И они в ту же ночь бежали. Потому что были «кулаками», работая от рассвета и до закакта. Вы можете представить какой силы террор пораждал такой уровень страха?
Давайте рефакторим код так, чтобы он больше не относился к ФП. Можно сделать класс с публичным свойством. Поскольку инкапсуляция не используется, было бы преувеличением назвать это ООП.
И в очередной раз инкапсуляцию связывают со способностью языка явным образом помечать поля класса как «private». Не об этом же инкапсуляция!
В вашем примере:
class User {
constructor ({name}) {
this.name = name;
}
...
}
+1, обычно и сам так пишу. Использовал слеши, чтобы не пугать впервые видящих подобное :)
По-поводу
str.join()
требующей итерируемое со строками — это тот самый случай из дзена — "Явное лучше неявного" и в какой-то мере "Принцип единой ответственности" (Single responsibility principle). От вас требуется явным образом привести объекты, пераданныеstr.join()
к строке, так как Вы отвечаете за представление каждого объекта в строковом виде, аstr.join()
лишь за их конкатенацию.Не соглашусь. Здесь затрагивается спецификация языка, в которой чёрным по белому написано:
tuple containing an item — ключевой момент. Спецификация не допускает каких либо других контейнеров в этом месте.
Питон, пакеты и библиотеки которые требуются для работы программы. Есть также бандлеры, которые с переменным успехом собирают Питон и зависимости в единый исполняемый файл.
Давайте немного отойдём от словаря. Пусть это сокет, в который отправляются данные. Опять два варианта:
Пример из Oracle-овского драйвера в Django:
Здесь нет проверок вроде
if self.is_closed
. Django не думает, что кому-то вздумается вызывать.close()
до покраснения :)Камрады, давайте разберём:
Теперь разберём ситуацию, в которой
В синтетическом тесте, try..except может оказаться быстрее, например:
У меня получилось, что
try..except
работает быстрее вплоть до 15% промахов.Но вся эта проблема, как мне кажется, высосана из пальца. EAFP это же не столько о скорости выполнения и о дефолтных значениях, сколько о самом принципе: не стоит погребать логику под
if valid
, еслиnot valid
— это исключительная ситуация.Если бы библиотеки Питона писались только на самом Питоне, то тогда бы подобных проблем было бы меньше. А теперь представьте, что вам нужна нативное расширение, например PIL/Pillow для обработки изображений? Есть два варианта — либо вы скачиваете кем-то скомпилированное и упаковонное расширение под вашу платформу и вашу версию Питона, либо скачиваете исходники и компилируете его сами!
pip
может сделать и то и другое, но для компиляции ему нужен собственно компилятор, заголовочные файлы Питона, исходники или бинарники зависимостей и т.д.npm пришёл из экосистемы, где всё пишется на JS. А в Питоне, помимо пакетов с "чистым" Питоном есть расширения, которые могут быть написаны на C/C++ и т.д. Отсюда и разница.
Вас как видимо смутило, что в Python, которому через пару лет третий десяток стукнет, до сих пор нет реализации модификаторов доступа и интерйфесов в том виде, каком они сделаны в Java / C#.
И дело даже не в договорённости на уровне языка и его культуры.
ОПА! А что нам даёт эта ошибка во время рантайма? В Java / C# это будет ошибка времени компиляции, а не выполнения.
С другой стороны тот же pylint спокойно отловит доступ к private/protected методам.
А с третьей — pylint тут и не нужен. Если программист по какой-либо причине использует приватные поля базового класса, или объекта — он должен полностью отдавать себе отчёт в том, что делает.
А как же утиная типизация? Есть у объекта метод __iter__ — значит по нему (скорее всего) можно итерироваться тем же for, нету — нельзя.
Чтобы не забыли? — вот тут соглашусь, это может быть удобно в больших проекта, но…
Pylint опять спешит на помощь и ловит неимплементированные методы абстракных классов!
— a наколько глубока интроспекция? Может где-то в глубине метода я вызываю функции, которые эти исключения бросают? А может где-то вылетают и другие исключения?
Всё вышепредложенное, в Питоне есть на уровне устоявшихся конвенций или может быть реализовано на уровне программ статического анализа кода.
И в очередной раз инкапсуляцию связывают со способностью языка явным образом помечать поля класса как «private». Не об этом же инкапсуляция!
В вашем примере:
name — вполне себе инкапсулированное поле.
А как же TinyCore?
Присоединяюсь. Почему о HD 599 в частности и об обновлённой линейке 5хх ни слова?