Які недоліки Python? [зачинено]


147

Сьогодні Python здається всім гнівом, і це не незаслужено - адже це справді мова, якою майже не подобається отримувати нову проблему. Але, як казав колись мудрець (називаючи його мудрою людиною лише тому, що я не маю уявлення про те, хто це насправді сказав; не впевнений, чи був він таким мудрим взагалі), щоб справді знати мову, вона не лише знає її синтаксис, дизайн тощо, переваги, але також і його недоліки. Жодна мова не ідеальна, деякі просто кращі за інші.

Отже, які, на вашу думку, об’єктивні недоліки Python.

Примітка: я не прошу тут порівняння мови (тобто C # кращий, ніж Python, тому що ... yadda yadda yadda) - більше об'єктивна (на деякий рівень) думка про те, які мовні особливості погано розроблені, чи є, що можливо дещо вам не вистачає в ньому тощо. Якщо потрібно використовувати іншу мову в якості порівняння, але лише для ілюстрації пункту, який важко було б розробити інакше (тобто для зручності розуміння)


50
Я думаю, що це корисне суб’єктивне питання, і було б соромно закривати його.
Ерік Вілсон

25
Здається, тут є фан-пітон, який просто спростовує всі відповіді на антипітон.
zvrba

2
@TMN: Це все ще трактує пробіли як лексеми, просто не повертає їх - і саме це робить граматика Пітона.

9
@Roger: конвенція про SO полягає в тому, щоб коментувати протизаконні коментарі. Оскільки це сайт для суб'єктивних думок, я не бачу причин для протиправних, особливо. без коментарів. Отже, я стою біля свого «прізвища».
zvrba

8
@zvrba: Downvotes все ще означає "не корисно", як завжди.

Відповіді:


109

Я використовую Python кілька регулярно, і в цілому я вважаю це дуже хорошою мовою. Тим не менш, жодна мова не є досконалою. Ось недоліки за важливістю для мене особисто:

  1. Це повільно. Я маю на увазі дійсно, дуже повільно. Багато разів це не має значення, але це, безумовно, означає, що вам потрібна інша мова для цих критично важливих бітів.

  2. Вкладені функції начебто всмоктуються тим, що ви не можете змінювати змінні у зовнішній області. Редагувати: Я все ще використовую Python 2 завдяки підтримці бібліотеки, і цей недолік дизайну дратує хек у мене, але, мабуть, він виправлений в Python 3 через нелокальне твердження. Не можу чекати, коли мочки, які я використовую, перенесуться, щоб цей недолік можна назавжди відправити до попелу.

  3. Не вистачає кількох функцій, які можуть бути корисними для бібліотечного / загального коду, а IMHO - це простота, яка сприймається до нездорових крайнощів. Найбільш важливі з них, які я можу придумати, - це визначені користувачем типи значень (я здогадуюсь, що їх можна створити за допомогою магії метакласу, але я ніколи не пробував) та параметр ref ref.

  4. Це далеко не метал. Потрібно написати примітивні нитки або код ядра чи щось таке? Удачі.

  5. Хоча я не заперечую проти відсутності можливості ловити семантичні помилки наперед, як компроміс за динамізм, який пропонує Python, я б хотів, щоб існував спосіб ловити синтаксичні помилки та дурні речі, такі як помилка імен змінних без фактичного запуску коду.

  6. Документація не настільки хороша, як мови, як PHP та Java, які мають міцну корпоративну підтримку.


60
@Casey, я не погоджуюся. Індекс жахливий - спробуйте пошукати withвислів чи методи на a list. Все, що охоплюється в підручнику, в основному недоступне. Мені набагато більше удачі з документацією Microsoft для C ++.
Марк Рансом

17
Близько 5 - просто використовуйте піфляки. Це написано, щоб виловити саме ті помилки.
Олександр Соловйов

4
Що стосується швидкості: зі зростанням PyPy, то багато користувачів Python тепер зможуть впоратися із проблемою швидкості лише за допомогою інтерпретатора із вбудованим JIT-компілятором (поки що користувачі Python 3 та користувачі модулів розширення C, якими не керує cpyext не мають цього варіанту).
ncoghlan

29
Я зневажаю документи Python. Вони гарніші, ніж більшість, напевне, але багато разів багато корисної інформації збирається на одну сторінку, як методи у рядках та списках - і всі типи послідовностей також згруповані разом. Коли я шукаю цю інформацію, я просто приземлююся на величезному вмісті, і мені доводиться шукати сторінку, щоб знайти те, що я хочу. Я також вважаю, що індекс на цих сторінках важко читати, і іноді важко сказати, який саме розділ я хочу.
Карсон Майєрс

5
Як відстань від металу може бути аргументом? Чи ніколи Python вважав себе системною мовою?
Марк Канлас

66

Я ненавиджу, що Python не може розрізняти декларацію та використання змінної. Вам не потрібно статичного введення, щоб це сталося. Було б просто добре сказати "це змінна, яку я свідомо декларую, і я маю намір ввести нове ім'я, це не помилка друку".

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

Однак я не можу зафіксувати цей факт. Ніщо в Python не заважає мені формувати перезапис або повторне використання змінних.

Підсумовуючи, я хотів би мати дві ключові слова в мові: varі let. Якщо я пишу в змінну, не оголошену жодною з них, Python повинен викликати помилку. Крім того, letоголошує змінні як лише для читання, тоді як varзмінні є "нормальними".

Розглянемо цей приклад:

x = 42    # Error: Variable `x` undeclared

var x = 1 # OK: Declares `x` and assigns a value.
x = 42    # OK: `x` is declared and mutable.

var x = 2 # Error: Redeclaration of existing variable `x`

let y     # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.

y = 23    # Error: Variable `y` is read-only

Зауважте, що типи все ще є неявними (але letзмінні для всіх намірів і цілей вводяться статично, оскільки їх неможливо відновити до нового значення, тоді як varзмінні все ще можуть бути динамічно набрані).

Нарешті, всі аргументи методу повинні бути автоматично let, тобто вони повинні бути лише для читання. Взагалі немає вагомих причин змінювати параметр, за винятком наступної ідіоми:

def foo(bar = None):
    if bar == None: bar = [1, 2, 3]

Це могло б замінити дещо іншу ідіому:

def foo(bar = None):
    let mybar = bar or [1, 2, 3]

6
Мені так хочеться, щоб у Python була заява "var". Окрім (дуже доброї) причини, яку ви заявляєте, це також полегшить читання коду, оскільки тоді ви можете просто переглядати сторінку, щоб побачити всі декларації змінних.
поштовх

25
Ніби розробники пітона ігнорували уроки минулого. Не декларування змінних, не декларування функцій - помилка, вперше допущена в 1950-х роках. Ті важко знайти помилок, які виникли внаслідок важко помітного помилки, були дивовижно вперше зроблені у 1950-х роках. Ця мовна помилка була зроблена (і пізніше виправлена) знову і знову. Декларування змінних не є великим тягарем. Це врятувало мою недопалок кілька разів. Я неминуче use strict;і use warnings;перл на сценарії будь-якого розміру. Python позбавив розробника занадто багато засобів налагодження.
Девід Хаммен

19
@David, Справедливість до python, це створить виняток, якщо ви спробуєте отримати доступ до змінної, якій не було призначено. Багато мов, у яких відсутні декларації, повернуть якесь значення за замовчуванням. Як наслідок, версія Python набагато менш проблемна, ніж ті.
Вінстон Еверт

1
@yi_H Пропозиція не мала бути сумісною назад або навіть реальною пропозицією. Питання полягало в тому, "які недоліки Python" ... ну, відсутність varі let(або подібний механізм) є недоліком. По-іншому: якби я був дизайнером Python, я зробив би щось подібне. Однак , майбутні версії можуть включати це під час завантаження спеціального пакету (подібного до __future__). Скажімо, import strict. Однак це не відбудеться, оскільки для цього потрібні синтаксичні хаки…
Конрад Рудольф

3
+1 Для додавання кращих функціональних можливостей програмування.
Еван Плейс

44

Моя основна скарга - це нарізання різьби, яке за багатьох обставин не є таким виконавським (порівняно з Java, C та іншими) через глобальне блокування інтерпретатора (див. Розмову "Всередині Python GIL" (PDF-посилання) )

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

Я дійсно не згоден з критикою документації, я вважаю, що вона відмінна і краща, ніж більшість, якщо не всі основні мови там.

Крім того, ви можете зловити багато помилок під час виконання, коли працює пілінт .


2
+1 для пілінта. Я про це не знав. Наступного разу, коли я роблю проект у Python, я спробую його випробувати. Крім того, схоже, що багатопотокове читання спрацьовує добре, якщо ви використовуєте Jython замість базової реалізації CPython. OTOH Jython дещо повільніше, ніж CPython, тому це може частково перемогти мету.
dimimcha

3
Нитка не підтримується добре? Бібліотеки, що врятують нитки, існують з початку до 2.1.
rox0r

2
Я знаю, що існує підтримка нитки, але порівняно з Java або C GIL дійсно знизить вашу продуктивність. Саме тому багатопроцесорний модуль віддається перевагу над різьбленням.
cmcginty

2
Документація хороша, якщо вам вдасться її знайти. Гугл Java-класи набагато простіше, ніж Python.
Брендан Лонг

@Casey Я уточнив формулювання у відповіді, оскільки тривання підтримується, якраз демонструє якесь дивне виконання (додано посилання та декілька посилань на документи)
1212

28

Можливо , відсутність статичної типізації, яка може запровадити певні класи помилок виконання , не варто додаткової гнучкості, яку забезпечує типінг качки.


5
Це правильно, хоча є такі інструменти, як PyChecker, які можуть перевірити наявність помилок компілятора на таких мовах, як C / Java.
Олівер Вайлер

24
Динамічне введення тексту - це свідоме дизайнерське рішення, а не недолік.
зниклий фактор

14
Це те саме, що говорити про слабкість Java - це відсутність динамічного набору тексту.
МАК

12
@missingfaktor, @MAK, очевидно , що друк качок був цільовою особливістю. Але більшість дизайнерських рішень вносять об'єктивні переваги та недоліки. Додана гнучкість коду є перевагою динамічного набору тексту, а додаткові класи потенційних помилок виконання - це недолік. Суб’єктивна частина полягає в тому, чи варта ця особливість.
Яків

6
Відсутність статичного набору тексту полегшує програмістам написання коду з помилками виконання. У C # int foo = 4; Console.Write(foo.Length);не компілюється, тому помилка "Int32 не має властивості Length" не може випадково пробитися до опублікованого програмного забезпечення. У python, якщо ви не запускаєте додаткові додаткові інструменти для пошуку подібних помилок, код, який отримує доступ до неіснуючих членів об'єктів, може залишатися невиявленим, доки він не закінчиться причиною помилок виконання.
Яків

27

Я думаю, що об'єктно-орієнтовані частини Python відчувають себе наче «застебнутими». Вся потреба в явній передачі "Я" кожному методу є симптомом того, що його компонент OOP не був чітко спланований , можна сказати; це також показує іноді бородавкові правила визначення розміру Python, які були піддані критиці в іншій відповіді.

Редагувати:

Коли я кажу, що об'єктно-орієнтовані частини Python відчувають себе «застебнутими», я маю на увазі, що часом сторона ООП відчуває себе досить непослідовною. Візьмімо, наприклад, Ruby: у Ruby все є об'єктом, і ви викликаєте метод, використовуючи знайомий obj.methodсинтаксис (за винятком, перевантажених операторів, звичайно); у Python теж все є об'єктом, але деякі методи ви називаєте функцією; тобто ви перевантажуєте, __len__щоб повернути довжину, але називаєте її, використовуючи len(obj)замість більш звичного (і послідовного) obj.lengthзагального для інших мов. Я знаю, що в цьому дизайнерському рішенні є причини, але вони мені не подобаються.

Крім того, у моделі OOP Python не вистачає будь-якого типу захисту даних, тобто немає приватних, захищених та публічних членів; ви можете імітувати їх, використовуючи _і __перед методами, але це щось некрасиво. Точно так же, Python НЕ зовсім отримати повідомлення обходячи аспект об'єктно - орієнтованого права, або.


17
Параметр self просто робить явним, що інші мови залишаються неявними. Ці мови явно мають параметр "Я".

13
@ Roger Pate: Так, але ця явна потреба у «самому» є якоюсь дратівливою (і, я б заперечував, хиткою абстракцією). Це також не сприймалося як обдумане дизайнерське рішення, але через "дивні" правила визначення області Python. Я не можу швидко знайти цю статтю, але є повідомлення по електронній пошті від Гвідо ван Россума, який чітко пояснює, чому потрібен параметр "Я".
mipadi

2
@Roger Pate: В об'єктно-орієнтованих мовах передача цілі в якості першого параметра все ще може вважатися деталлю реалізації. Моя думка, однак, не в тому, чи це гарна ідея чи ні; справа в тому , що в Python, це НЕ з - за свідомого рішення дизайну, а працювати навколо бородавки в системі оглядового.
mipadi

3
@mipadi: Оновлення має кращі міркування (тому я зніму нижчу оцінку), але якщо ви розглядаєте len як оператора, який ви перевантажуєте, це більше OO в Python. Хочеться побачити приклад або міркування про те, як Python неправильно передає повідомлення.

8
Явне самовизначення є наслідком того, що методи - це лише функції (і, як зазначив Вінстон, неявні локальні мінливі декларації). Вам не подобається таке дизайнерське рішення, але називати OOP "зафіксованим" мовою, де все є доступним як об'єкт під час виконання, нерозумно.
ncoghlan

19

Що мені не подобається в Python:

  1. Тематика (я знаю, що її вже згадувалося, але варто згадати в кожному дописі).
  2. Немає підтримки багаторядкових анонімних функцій ( lambdaможе містити лише один вираз).
  3. Відсутність простий , але потужний вхід читання функції / класу (як cinі scanfв C ++ і C або Scannerв Java).
  4. Усі рядки за замовчуванням не є унікодом (але зафіксовані в Python 3).

5
Щодо (2), я думаю, це компенсується можливістю мати вкладені функції.
Конрад Рудольф

3
@KonradRudolph Основна моя особливість із вкладеними функціями замість багаторядкових лямбда - це заміна читання.
CookieOfFortune

2
@wkschwartz: raw_inputі 'sys.stdin' є досить босоніжними. Вони не підтримують отримання форматованого введення (наприклад, щось на зразок "% d:% d:% d"% (година, хвилина, сек), щоб вчасно прочитати). Поки що Python не має нічого, що наближається до функціональності scanf (в C) або Scanner (Java).
МАК

2
@limscoder: У Java всі рядки за замовчуванням є unicode. Я не бачу вагомих причин мати окремі класи str та unicode. IMHO, рядки та масиви байтів не повинні бути представлені однією абстракцією. Клас рядків повинен бути для зберігання та маніпулювання текстом - внутрішнє представлення якого нас насправді не цікавить. Ми не повинні робити такі речі, як укорочення / заміна / видалення / вставлення в певному байті в рядку - ми хочемо це зробити за певним символом . Легко забути відмінність, і ваш код підірветься, коли його подають не англійською мовою.
MAK

1
@limscoder: якщо ви хочете побачити простий унікод, спробуйте Tcl. Мені довелося перейти з Tcl на Python кілька років тому, і хлопчик був здивований тим, наскільки примітивна підтримка Unicode Python знаходиться в порівнянні. Це справді невидимо в Tcl, і великий біль у python.
Брайан Оуклі

18

Аргументи за замовчуванням із змінними типами даних.

def foo(a, L = []):
    L.append(a)
    print L

>>> foo(1)
[1]
>>> foo(2)
[1, 2]

Зазвичай це результат деяких тонких помилок. Я думаю, що було б краще, якщо він створив новий об'єкт списку, коли потрібен аргумент за замовчуванням (а не створення одного об'єкта, який потрібно використовувати для кожного виклику функції).

Редагувати: Це не величезна проблема, але коли щось потрібно згадати в документах, це зазвичай означає, що це проблема. Це не потрібно.

def foo(a, L = None):
    if L is None:
        L = []
    ...

Особливо, коли це мало бути за замовчуванням. Це просто дивна поведінка, яка не відповідає тому, що ви очікували, і не корисна для великої кількості обставин.


Я бачу багато скарг на це, але чому люди наполягають на тому, що порожній список (що змінює функцію) як аргумент за замовчуванням? Це справді така велика проблема? Тобто це справжня проблема?
Мартін Вілканс

8
Це порушує принцип найменшого здивування. Не можна було б сподіватися, що параметри функції виживуть під час викликів.
аїб

Це наслідок того, що це сценарна мова. Ви будете натикатися лише на цю помилку ТАКІ, і ніколи більше. Виявлення цієї помилки для себе насправді дає вам удар в зад, щоб нагадати, що так, це все-таки мова сценаріїв. І це лише тому, що мова є такою гарною, що приховує сценарій сценарію (якщо припустити, що ви ним правильно користуєтесь).
Зоран Павлович

@ZoranPavlovic з цікавості, чому це наслідок того, що це сценарна мова? Здається, це проблема з тим, коли дані пов'язані, і тому, що списки є змінними (це дві речі, які зазвичай є хорошими, але в кінцевому підсумку є поганими). Ця ж проблема може трапитися і в мові без сценарію, якщо ви прив'язуєте дані під час створення функції, а не створюєте новий список кожного разу, коли функція викликається.
jsternberg

@aib: Я не думаю, що цей параметр, як і будь-який інший об'єкт Python, - це вказівник на об'єкт. У цьому випадку об'єкт є змінним, а змінна прив'язується при оголошенні функції. Параметр "виживає через виклики", але те, що виживає, - це посилання на об'єкт, що змінюється.
Патрік Коллінз

14

Деякі особливості Python, які роблять його настільки гнучким як мова для розробки, також розглядаються як основні недоліки тих, які використовуються для статичного аналізу "цілої програми", що проводиться процесом компіляції та з'єднання на таких мовах, як C ++ та Java.

  • Неявне оголошення локальних змінних

Локальні змінні оголошуються за допомогою звичайного оператора призначення. Це означає, що змінні прив’язки в будь-якій іншій області вимагають, щоб компілятор вибирав явні анотації (глобальні та нелокальні декларації для зовнішніх областей, позначення доступу до атрибутів, наприклад, області застосування). Це значно зменшує кількість котлоагрегату, необхідного при програмуванні, але означає, що необхідні інструменти статичного аналізу сторонніх сторін (такі як піфляки) для здійснення перевірок, які обробляються компілятором мовами, які вимагають явних оголошень змінних.

  • "Мавпа патч" підтримується

Вміст модулів, об’єктів класу і навіть вбудований простір імен можна змінювати під час виконання. Це надзвичайно потужно, що дозволяє багато надзвичайно корисних методик. Однак ця гнучкість означає, що Python не пропонує деяких функцій, спільних для мов OO зі статичним набором. Найголовніше, що параметр "self" для примірників методів є явним, а не неявним (оскільки "методи" не повинні визначатися всередині класу, вони можуть бути додані пізніше, модифікуючи клас, тобто це не особливо практично) передавати посилання на екземпляр неявно) та керувати доступом до атрибутів не можна легко застосувати на основі того, чи є код "всередині" чи "зовні" класу (оскільки це відмінність існує лише під час виконання визначення класу).

  • Далеко від металу

Це також стосується багатьох інших мов високого рівня, але Python прагне абстрагувати більшість апаратних деталей. Мови програмування систем, такі як C та C ++, все ще набагато краще підходять для прямого доступу до апаратного забезпечення (однак, Python цілком із задоволенням розмовлятиме з ними або через модулі розширення CPython, або, ще більш портативно, через ctypesбібліотеку).


12
  1. Використання відступів для блоків коду замість {} / begin-end, як би там не було.
  2. Кожна нова сучасна мова має належне лексичне визначення, але не Python (див. Нижче).
  3. Хаотичні документи (порівняйте з документацією Perl5, яка чудово).
  4. Куртка з протокою (існує лише один спосіб зробити це).

Приклад розбитого масштабу; стенограма з сеансу перекладача:

>>> x=0
>>> def f():
...     x+=3
...     print x
... 
>>> f()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

globalі nonlocalключові слова були введені для виправлення цієї дизайнерської дурості


2
що стосується обстеження, то, можливо, варто того, щоб цікаво подивитись на python.org/dev/peps/pep-3104, щоб зрозуміти міркування поточного методу.
Вінстон Еверт

Погодьтеся з +1. Отже, +1.
Яс

34
Маючи один спосіб зробити це - перевага. Коли ви читаєте чужий код, ви не розшифровуєте жодного разу твердження. Після того, як ідіоми будуть увімкнені у вашому мозку, у вас має бути миттєве розпізнавання.
rox0r

9
Повністю згоден з @ rox0r. "Пряма куртка" запобігає різного роду синтаксичним війнам.
keithjgrant

8
Якщо чесно, мені дуже рідко потрібні ключові слова globalабо nonlocalPython. Так рідко, що я забуваю, що ця проблема існує, і мені доводиться повторно гуглювати її кілька разів, коли вона з’являється, незважаючи на те, що я пишу код Python щодня на роботі. Для мене код, який потребує модифікації глобальних змінних (або, що ще гірше, зовнішніх неглобальних змінних) - це запах коду. Зазвичай є (не завжди) кращий спосіб.
Бен

11

Я вважаю поєднання python об'єктно-орієнтованого this.method()та процедурно-функціонального method(this)синтаксису дуже неспокійним:

x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)

Це особливо погано, оскільки велика кількість функцій (а не методів) просто скидаються в глобальний простір імен : методи, що стосуються списків, рядків, чисел, конструкторів, метапрограмування, всі об'єднані в один великий алфавітно-відсортований список.

Принаймні, такі функціональні мови, як F #, мають усі функції, правильно розподілені в модулях:

List.map(x)
List.reversed(x)
List.any(x)

Отже, вони не всі разом. Крім того, цей стандарт дотримується у всій бібліотеці, так що принаймні він відповідає.

Я розумію причини виконання функції в порівнянні з методом , але я все ще думаю, що це погана ідея їх змішувати так. Я був би набагато щасливішим, якби дотримувався синтаксис методу, принаймні для звичайних операцій:

x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()

Незалежно від того, мутують вони методи чи ні, використання їх як методів на об'єкті має ряд переваг:

  • Єдине місце для пошуку "загальних" операцій над типом даних: інші бібліотеки / тощо. можуть бути інші химерні речі, які вони можуть зробити для типів даних, але операції "за замовчуванням" - всі в методах об'єкта.
  • Не потрібно постійно повторювати Moduleдзвінки під час дзвінка Module.method(x). Беручи приклад функціонального списку вище, чому я повинен постійно говорити List? Він повинен знати, що це є, Listі я не хочу викликати Navigation.map()функцію на ньому! Використання x.map()синтаксису зберігає його СУХО та однозначно.

І звичайно, він має переваги перед способом цього " все-у-глобальному"-просторі імен . Справа не в тому, що нинішній спосіб не в змозі зробити справи. Це навіть досить коротко ( len(lst)), оскільки нічого не розділено на імена! Я розумію переваги використання функцій (поведінка за замовчуванням тощо) перед методами, але все одно мені це не подобається.

Це просто безладно. А у великих проектах безладдя - ваш найгірший ворог.


1
так ... я дуже сумую за стилем LINQ (я впевнений, що LINQ не перший, хто його застосував, але я з ним найбільше знайомий) обробка списку.
CookieOfFortune

1
Не думайте про len (x) як про метод. "len" - це функція. У Python є функції та методи, і я не бачу нічого поганого в цьому підході. Відсутність належних функцій, як правило, є джерелом безлічі непотрібних наборів тексту.
rbanffy

Я знаю len(), це функція, і які переваги. Я також заявив, чому я вважаю це поганою ідеєю, чому я вважаю, що глобальні функції є особливо поганою ідеєю, і чому я думаю, що методи забезпечують зручний метод організації та визначення вашого функціоналу =)
Haoyi

Я не думаю, що 42 (або це 43?) Ключових слів - це «велике» число. Це також включає в себе такі речі , як def, classі інші виклики , не функція. Порівняйте це зі 100+ у більшості інших популярних мов. Крім того , розглянемо лінію від import this: Namespaces are one honking great idea -- let's do more of those!. Я думаю, ви можете неправильно зрозуміти простори імен Python;)
Вейн Вернер

8

Відсутність гомонічності .

Python довелося чекати 3.x, щоб додати ключове слово "з". Будь-якою гомоніконімічною мовою це можна було б тривіально додати до бібліотеки.

Більшість інших питань, які я бачив у відповідях, мають один із 3 типів:

1) Речі, які можна виправити за допомогою інструментарію (наприклад, піфлейки) 2) Деталі впровадження (GIL, продуктивність) 3) Речі, які можна виправити за допомогою стандартів кодування (тобто функції, за які люди бажають, щоб їх не було)

№2 не є проблемою з мовою, ІМО №1 та №3 не є серйозними проблемами.


1
withбув доступний з Python 2.5 з from __future__ import with_statement, але я згоден, я іноді виявив , що шкода , що заяви , як if/ for/ print/ і т.д. є «спеціальним» замість звичайних функцій
DBR

7

Python - це моя улюблена мова, оскільки вона дуже виразна, але все одно не дає вам робити занадто багато помилок. У мене ще є кілька речей, які мене дратують:

  • Немає справжніх анонімних функцій. Лямбда може використовуватися для функцій з одним оператором, а withоператор може використовуватися для багатьох речей, де ви використовували б блок коду в Ruby. Але в деяких ситуаціях це робить дещо незграбнішими, ніж вони мали б бути. (Далеко не такий незграбний, як це було б на Яві, але все ж ...)

  • Певна плутанина у відношенні між модулями та файлами. Запуск "python foo.py" з командного рядка відрізняється від "import foo". Відносний імпорт в Python 2.x також може спричинити проблеми. Тим не менш, модулі Python набагато краще, ніж відповідні функції C, C ++ і Ruby.

  • Явне self. Незважаючи на те, що я розумію деякі причини цього, і хоча я використовую Python щодня, я, як правило, помиляюсь про це. Інша проблема з цим полягає в тому, що робити клас з модуля стає трохи нудно. Явне самоврядування пов'язане з обмеженою сферою застосування, на яку скаржилися інші. Найменша сфера застосування в Python - це область функцій. Якщо ви зберігаєте свої функції невеликими, як слід, це не є проблемою само по собі, і IMO часто надає більш чистий код.

  • Деякі глобальні функції, такі як, наприклад len, те, що ви можете очікувати як метод (який він насправді знаходиться поза кадром).

  • Значне відступ. Не сама ідея, яка, на мою думку, є чудовою, але оскільки це єдина річ, яка заважає багатьом людям спробувати Python, можливо, Python буде краще з деякими (необов'язковими) символами початку / кінця. Ігноруючи цих людей, я міг би повністю жити з примусовим розміром для відступу теж.

  • Що це не вбудована мова веб-браузерів, а не JavaScript.

З цих скарг я лише найперший, який мені досить хвилює, що я думаю, що його слід додати до мови. Інші досить незначні, за винятком останнього, що було б чудово, якби це сталося!


+1 Мене задає питання, чи писати, datetime.datetime.now()коли один проект міг би написати, datetime.nowа потім змішати два проекти, один спосіб написання цього виключає інший, і, звичайно, цього не сталося б у Java, який не назвав би модуль таким же, як файл (?) якщо ви бачите, як загальний спосіб, здається, модуль плутає нас з файлом, коли обидва способи практикуються і явні, selfя все одно намагаюся зрозуміти, оскільки виклики не мають такої ж кількості аргументів, як функції. І ви можете подумати, що пітон VM є повільним?
Niklas Rosencrantz

Що стосується вашої проблеми з явним ключовим словом. Я можу запропонувати використовувати для цього хороший IDE пітона? Я знаю, що PyDev на Eclipse автоматично завершує самостійну частину підпису функції, якщо він виявить, що ви пишете всередині класу.
Зоран Павлович

5

Python не повністю зрілий: мова python 3.2 в цей час має проблеми з сумісністю з більшістю розповсюджених в даний час пакетів (зазвичай вони сумісні з python 2.5). Це великий недолік, який в даний час вимагає більше зусиль для розробки (знайдіть необхідний пакет; перевірте сумісність; зважте, вибираючи недобрий пакет, який може бути більш сумісним; візьміть найкращу версію, оновіть її до 3.2, що може зайняти кілька днів; потім починайте робити щось корисне).

Ймовірно, в середині 2012 року це буде меншим недоліком.

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

Зрілість в одному головному сенсі означає, що команда може використовувати цю технологію і дуже швидко працювати і працювати без прихованих ризиків (включаючи проблеми сумісності). Пакети пітонів третьої сторони та багато додатків не працюють під 3.2 для більшості пакетів сьогодні. Це створює більше роботи з інтеграції, тестування, повторного вдосконалення самої технології замість вирішення проблеми під рукою == менш зріла технологія.

Оновлення за червень 2013 року: у Python 3 все ще є проблеми зрілості. Кожен настільки часто член команди згадує необхідний пакет, після чого скаже "за винятком лише 2.6" (у деяких з цих випадків я реалізував рішення через localhost socket, щоб використовувати пакет, що містить лише 2.6 з 2.6, а решта наші інструменти залишаються з 3.2). Навіть MoinMoin, вікі з чистого пітона, написаний у Python 3.


2
Я погоджуюся з вами лише в тому випадку, якщо ваше визначення зрілості не сумісне з версією, несумісною за дизайном .
thepang

3
Я погоджуюся, що два несумісні потоки python - це проблема (хоча зрозуміло, чому це було зроблено), але я не вважаю це питанням "зрілості".
Вінстон Еверт

Зрілість в одному сенсі означає, що команда може використовувати технологію та дуже швидко працювати та працювати без прихованих ризиків (включаючи проблеми сумісності). Пакети пітонів третьої сторони та багато додатків не працюють під 3.2 для більшості пакетів сьогодні. Це створює більше роботи з інтеграції, тестування, повторного вдосконалення самої технології замість вирішення проблеми під рукою == менш зріла технологія.
Джонатан Клайн IEEE

2
Потім просто використовуйте Python 2.x. Ви знаєте ... версія, якою користуються всі. Або прочитайте документацію на пакунки протягом 2 секунд, щоб зрозуміти, з якими версіями вона сумісна.
jsternberg

2
"Тільки тому, що python 3.0 був випущений деякий час, не означає його версію, яку ви повинні використовувати. Python 3.0 і 2.x розробляються одночасно. Сподіваюся, що в майбутньому ми все зможемо використовувати python 3.0, але наразі використання 2.x є гарним рішенням "-> Це 500-символьний спосіб сказати: Він ще не зрілий.
Джонатан Клайн IEEE

4

Область застосування Python дуже порушена, що робить об’єктно-орієнтоване програмування в Python дуже незручним.


8
ви можете навести приклад? (Я впевнений, що ви маєте рацію, але я хотів би приклад)
Winston Ewert

24
Мені подобається Python, але я абсолютно зневажаю, що потрібно ставити self.перед усіма посиланнями на властивість і метод екземпляра. Це робить неможливим використання Python для створення DSL, як це так легко зробити в Ruby.
Адам Кросленд

35
Я не вважаю себе незручним, мені подобається явність.
Вінстон Еверт

9
Я не бачу, у чому полягає велика справа в явній самості. У C ++, Java та D люди часто роблять явні змінні членами явними за умовами, наприклад, префіксування їх підкресленням.
dimimcha

7
Ви використовуєте self у методах, відмінних від їх декларації: def foo (self) but self.foo (). Я вважаю, що ця суміш чіткого визначення, але неявна закулісна робота не надто симпатична.
LennyProgrammers

4

Мої схвалення про Python:

  • OOP з підключеним процесором (див. Відповідь @ mipadi для розробки цього питання)
  • Порушена реалізація лямбда
  • Сфера застосування
  • У стандартній бібліотеці немає постійних колекцій
  • Погана здатність до вбудованих DSL

Чому потік?
зниклий фактор

Я не переслідувач, але чи можете ви пояснити, чому ви вважаєте, що OO зафіксовано? У Python завжди був OO, це основна частина мови.
Daenyth

Дивіться відповідь @ mipadi.
зниклий фактор


4

Модифікатори доступу в Python не підлягають застосуванню - ускладнює написання добре структурованого модульованого коду.

Я вважаю, що це частина розбитого обліку @ Мейсона - велика проблема загалом з цією мовою. Для коду, який повинен бути читабельним, здається, досить складно зрозуміти, що може і що має бути в області застосування та яке значення буде у будь-який момент часу - я зараз думаю про перехід від мови Python через ці недоліки .

Тільки тому, що "ми всі погоджуємось на дорослих" не означає, що ми не робимо помилок і не працюємо краще в сильній структурі, особливо коли працюємо над складними проектами - відступ та безглузді підкреслення не здаються достатніми. .


Отже, відсутність контролю доступу погана ... але явне розміщення записів змінної до будь-якого не локального простору імен також погано?
ncoghlan

@ncoghlan: 1 - ця функція є стандартною для багатьох сучасних мов, залежно від налаштування проекту. 2 - Це під контролем програміста. 3 - не впевнений, що в цьому так чудово - ви можете легко керувати своїм масштабом за допомогою кількох налаштувань проекту на більшості складених мов / IDE. Якщо "ми всі погоджуємося з дорослими", ми повинні мати можливість приймати власні рішення та коригувати сферу діяльності відповідно до конкретного рівня комфорту.
Вектор

2
Вся справа в тому, що люди, які просять "примусового контролю доступу", просять нас вийняти одну із самих речей, що робить Python такою чудовою мовою клею: розробникам навмисно важко контролювати, як згодом використовується їхній код. Скільки шаблонів котлів у моделях C ++ та Java існує виключно для роботи навколо примусового контролю доступу? Я точно можу зрозуміти людей, які вирішили не використовувати Python з цих причин, але статичне виконання ніколи не стане заміною жорсткого тестування.
ncoghlan

1
@ncoghlan - для мене великі речі про Python - це витонченість синтаксису, а стислість - виразність. І, як я вже сказав, масштабування має менше спільного з програмістами, які возиться з речами, які вони не повинні, ніж це стосується структури коду та організації - тому поняття «згода на дорослих» є суперечливою. Я працюю над складними проектами, а не простими утилітами та сценаріями - код повинен бути ретельно модульований та структурований - модифікатори доступу є одним із найважливіших способів забезпечення цього.
Вектор

1
А перегляд коду, навчання та аналіз зв'язку - це інші. На мій погляд, примусовий контроль доступу потрапляє в те саме відро, що і статичне введення тексту: вони допомагають забезпечити додаткову впевненість у правильності (але недостатньо, щоб уникнути необхідності в широкому тестуванні), але з високою вартістю в продуктивності розвитку. (На практичному рівні елементи керування доступом до атрибутів класу також не підходять до об'єктної моделі Python, де методи - це лише звичайні функції, отримані з класів. Межа для класів "всередині / зовні" насправді не існує, тому не може бути примусово)
ncoghlan

3
  1. Продуктивність не є хорошою, але покращується з pypy,
  2. GIL запобігає використанню нитки для прискорення коду (хоча це, як правило, передчасна оптимізація),
  3. Це корисно лише для програмування додатків,

Але він має деякі чудові функції викупу:

  1. Він ідеально підходить для RAD,
  2. Інтерфейс з C (і для C вбудовувати інтерпретатора python) легко,
  3. Це дуже легко читається,
  4. Це легко навчитися,
  5. Це добре задокументовано,
  6. Батареї дійсно включені, стандартна бібліотека величезна, а піпі містить модулі практично для всього,
  7. У ньому є здорове співтовариство.

Що надихнуло згадати переваги? Питання до проблем. У будь-якому випадку, що ти означає, що це корисно лише для програмування додатків? Які ще програми існують? Що конкретно це не добре?
thepang

5
Я перерахував переваги, тому що думаю, що вони переважують мінуси. Ви коли-небудь намагалися реалізувати модуль ядра Linux в python.
dan_waterworth

3

Я віддаю перевагу python, і перший недолік, який мені спадає на думку, це коли коментувати заяву, як if myTest():тоді, ви повинні змінити відступ у всьому виконаному блоці, який би вам не доводилося робити з C або Java. Насправді в python замість того, щоб коментувати пункт-if, замість цього я почав коментувати це так: `if True: #myTest (), тому мені також не доведеться змінювати наступний блок коду. Оскільки Java і C не покладаються на відступи, це полегшує коментування тверджень за допомогою C та Java.


1
Ви б серйозно відредагували код C або Java, щоб змінити рівень блоку якогось коду, не змінюючи його відступ?
Бен

4
@Ben Тимчасово, так ...
альтернатива

1
@ben ж тут.
Крістофер Махан

2
Я використовую трюк переходу if something()на if False and something(). Ще одна хитрість - "коментувати", використовуючи багаторядковий рядок.
Мартін Вілканс

1
@ Мартин звичайно! якщо помилково ...
Крістофер Махан

3

Багаторазова відправка не добре поєднується зі встановленою системою одноразового типу та не є дуже ефективною.

Динамічне завантаження - це велика проблема в паралельних файлових системах, де семантика, схожа на POSIX, призводить до катастрофічних уповільнень для операцій з інтенсивними метаданими. У мене є колеги, які спалили чверть мільйона основних годин, просто отримуючи Python (з numpy, mpi4py, petsc4py та іншими модулями розширення), завантаженими на 65 кер. (Моделювання дало значні нові наукові результати, тому воно того варте, але це проблема, коли спалюється більше, ніж барель нафти, щоб завантажувати Python один раз.) Неможливість статичного зв’язку змусила нас піти на великі суперечки, щоб отримати розумні рази завантаження в масштабі, включаючи виправлення libc-rtld для забезпечення dlopenколективного доступу до файлової системи.


Нічого собі, здається, високотехнологічним, чи є у вас довідковий матеріал, приклади, дописи в блогах чи статті з цього питання? Цікаво, чи можу я піддатися подібним випадкам найближчим часом.
Вінсент

Арон виступив з доповіддю на SciPy 2012 . dlopenМатеріал в нашій collfs бібліотеці. Це сховище також містить додаткові трюки з zipimport, натхненні кешуванням шляху Ашера Ленґтона. Ми працюємо над кращим розповсюдженням та папером.
Джед

3
  • чимало бібліотек та програмного забезпечення, які широко використовуються сторонніми компаніями, які широко використовуються, є не пітонічними. Кілька прикладів: soaplib, openerp, reportlab. Критика поза сферою, вона існує, вона широко використовується, але це робить культуру пітона заплутаною (це шкодить девізу, який говорить: "Має бути один - і бажано лише один - очевидний спосіб це зробити"). Відомі пітонічні успіхи (наприклад, джанго чи трак), здаються, є винятком.
  • потенційно необмежена глибина абстрагування екземпляра, класу, метакласу є концептуально красивою та унікальною. Але для того, щоб засвоїти його, ви повинні глибоко знати інтерпретатора (в якому порядку інтерпретується код python тощо). Він не широко відомий і використовується (або використовується правильно), в той час як подібні чорні магії, такі як C # generics, тобто концептуально більш згорнуті (IMHO), здаються більш широко відомими та використовуються пропорційно.
  • щоб добре зрозуміти модель пам’яті та нарізки, вам доведеться бути досить досвідченим з python, тому що немає всеосяжної характеристики. Ви просто знаєте, що працює, можливо, тому, що ви прочитали джерела перекладача або досвідчені химерності та дізналися, як їх виправити. Наприклад, є лише сильні або слабкі посилання, а не м'які та фантомні відбиття Java. У Java є нитка для збору сміття, поки немає офіційної відповіді про те, коли збирання сміття відбувається в python; ви можете просто спостерігати, що збирання сміття не відбувається, якщо не виконується код python, і зробити висновок, що це, мабуть, трапляється іноді при спробі виділення пам'яті. Може бути складним, коли ви не знаєте, чому заблокований ресурс не був випущений (мій досвід про це був mod_python в freeswitch).

Так чи інакше, Python - моя головна мова вже 4 роки. Бути фанбоями, елітистами або одноманітниками не є частиною культури пітона.


+1. Спеціальна модель для пам’яті та набору різьби увімкнена. Але FWIW, збирач сміття Java, що знаходиться в потоці (і більшість всього іншого про GC), не є аспектом мови Java або специфікацій VM, як такої, а є питанням конкретної реалізації JVM. Однак основний JVM Sun / Oracle - це широко документально підтверджена поведінка та налаштування WC GC, настільки, що є цілі книги, опубліковані про налаштування JVM. Теоретично можна документувати CPython таким же чином, незалежно від мовних специфікацій.
Ендрю Янке

2
  • Дивний OOP:
    • len(s)за допомогою __len__(self)та інших "спеціальних методів"
    • додаткові спеціальні методи, які можна отримати від інших спеціальних методів ( __add__і __iadd__для +та +=)
    • self як перший параметр методу
    • ви можете забути викликати конструктор базового класу
    • відсутні модифікатори доступу (приватні, захищені ...)
  • немає постійних визначень
  • відсутність незмінності для користувацьких типів
  • GIL
  • низька продуктивність, що призводить до поєднання Python та C та проблем із збірками (шукаючи C libs, залежність від платформи ...)
  • погана документація, особливо в сторонніх лайках
  • несумісність між Python 2.x та 3.x
  • погані інструменти аналізу коду (порівняно з тими, які пропонуються для мов, які набираються статично, таких як Java або C #)

5
Особисто я вважаю, що несумісність між 2.x та 3.x є однією з найбільших переваг Python. Звичайно, це також є недоліком. Але зухвалість розробників до руйнування зворотної сумісності також означає, що їм не доводилося нескінченно переносити крихту. Більше мов потребує такого ремонту.
Конрад Рудольф

0

"Незмінюваність" - це не зовсім сильна сторона. Номери, кортежі та рядки AFAIK незмінні, все інше (тобто об'єкти) змінюється. Порівняйте це з функціональними мовами, такими як Erlang або Haskell, де все незмінне (як мінімум).

Однак Immutability насправді світить паралельністю *, що також не є сильною стороною Python, так що, принаймні, це є наслідком.

(* = Для ниткопідбирачів: я маю на увазі сумісність, яка принаймні частково паралельна. Я думаю, що в Python нормально з однонитковою одночасністю, в якій незмінність не так важлива. (Так, любителі FP, я знаю, що незмінність - це чудово навіть без одночасності.))


0

Я хотів би мати явно паралельні конструкції. Найчастіше, коли я пишу таке розуміння списку

[ f(x) for x in lots_of_sx ]

Мене не хвилює порядок обробки елементів. Іноді мені навіть байдуже, в якому порядку вони повертаються.

Навіть якщо CPython не може зробити це добре, коли мій f чистий Python, така поведінка може бути визначена для інших застосувань.


// spawn купа ниток // передайте чергу черги всім потокам que.extend ([x для x у lot_of_sx]) que.wait () # Зачекайте, поки всі lot_of_sx будуть оброблені потоками.
Зоран Павлович

0

Python не має оптимізації для виклику хвостів, здебільшого з філософських причин . Це означає, що повторення хвоста на великих структурах може коштувати O (n) пам’яті (через непотрібний стек, який зберігається) і вимагатиме від вас переписати рекурсію як цикл для отримання O (1) пам’яті.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.