python - язык очень высокого уровня или не очень?...[re: python. учеб]

klyv

Хорошо в этой книге звучит фраза "Питон - язык ОЧЕНЬ высокого уровня" :)
дык а чё? так и есть.

agent007new

дык а чё? так и есть.
И чего же в Питоне ОЧЕНЬ высокого такого?

klyv

хотябы то, что он - динамический

agent007new

хотябы то, что он - динамический
Если по этому параметру судить, то PHP и JavaScript тоже языки очень высокого уровня. Это не повод называть язык очень крутым. Мне, например, больше нравится жесткая типизация и максимум проверок во время компиляции

timefim

то PHP и JavaScript тоже языки очень высокого уровня
Да.
Это не повод называть язык очень крутым.

Каким образом у тебя связаны понятие крутости и высокоуровневости?
Мне, например, больше нравится жесткая типизация и максимум проверок во время компиляции

Ты хочешь поговорить об этом?

agent007new

то PHP и JavaScript тоже языки очень высокого уровня
Да.
Если высокоуровневость языка определять по статической/динамической типизации, то да, так оно и есть. Но по моим представлениям и по определению на вики, высокоуровновость - это совсем другое.
Основная черта высокоуровневых языков — это абстракция, то есть введение смысловых конструкций, кратко описывающих такие структуры данных и операции над ними, описания которых на машинном коде (или другом низкоуровневом языке программирования) очень длинны и сложны для понимания.

Это не повод называть язык очень крутым.
Каким образом у тебя связаны понятие крутости и высокоуровневости?
В данном контексте я употребил это как синонимы

Ты хочешь поговорить об этом?
Не особо

slonishka

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

nikita270601

чотка абстрактные

slonishka

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

slonishka

абстракт-хоп!

timefim

И ты не считаешь что python имеет более высокий уровень абстракции чем плюсы?

sergeikozyr

Согласен. Только, конечно, не насчёт т.н. статической типизации в традиционных императивных языках, вроде цешарпа или джавы, а насчёт алгебраической типизации - она очень серъёзно повышает выразительность языка и позволяет писать более понятный код.

sergeikozyr

И ты не считаешь что python имеет более высокий уровень абстракции чем плюсы?
Оно, конечно, так. Но мне его уровня абстракции в некоторых моментах не хватает.

timefim

Но мне его уровня абстракции в некоторых моментах не хватает.
В каких таких моментах?

klyv

Если высокоуровневость языка определять по статической/динамической типизации, то да, так оно и есть. Но по моим представлениям и по определению на вики, высокоуровновость - это совсем другое.
Причём тут динамичность типизации?
Динамическая типизация есть во всех языках, где есть ООП.
А вот динамичность типов - не во всех.

sergeikozyr

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

agent007new

И ты не считаешь что python имеет более высокий уровень абстракции чем плюсы?
Не считаю: в этом плане они абсолютно одинаковы. Те же классы, те же объекты, которые определяет программист. Есть разница в их синтаксисе, способе работы, но не более. У этих языков разница в библиотеках, в конструкциях языка, из-за которых некоторые вещи делаются проще то на одном языке, то на другом.

klyv

Но мне его уровня абстракции в некоторых моментах не хватает.
Филосовские трактаты пишут на естественных языках ;)

sergeikozyr

Если ты ничего кроме цепепе/цешарпа/бидона/т.п. не юзал, то лучше помолчи ;)

sergeikozyr

Не считаю: в этом плане они абсолютно одинаковы. Те же классы, те же объекты, которые определяет программист. Есть разница в их синтаксисе, способе работы, но не более. У этих языков разница в библиотеках, в конструкциях языка, из-за которых некоторые вещи делаются проще то на одном языке, то на другом.
это точно. Сделал себе строки - отнаследовал от std::string - добавил всяких split, strip, slice, и не сильно чувствую разницу между питоном и цепепе :grin:

timefim

Периодическое отслеживание куда и зачем уходит память тебя не смущает?

agent007new

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

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

agent007new

Периодическое отслеживание куда и зачем уходит память тебя не смущает?
Не поверишь, очень редко занимаюсь такими вещами: если грамотно использовать С++, то все прекрасно работает. Сейчас набрал в гугле "Python memory leak", дофига ссылок нашлось. Я особо их не читал, что там за проблемы, но одна из первых ссылок - ссылка на какую-то тулзу "Python Memory Leak Detector". Если даже такая штука есть, то не все здесь наверное чисто и просто.
В общем, как я уже сказал - это всего лишь одна из фич языка: если ты хочешь контролировать, когда тебе освобождать ресурсы, то выбираешь одно, если не хочешь париться по этому поводу - другое.
Как пример могу привести хваленую джаву, в которой заявлялось как там все просто и красиво с памятью. Сейчас уже деталей не помню - пару лет назад было, на прошлой работе мне достался в наследство довольно крупный проект, в котором я обнаружил утечку памяти. Из-за каких-то циклических ссылок сборщик мусора отказывался собирать бесхозные объекты, которые образовывали цикл, но никем больше не использовались. Чтобы развязать этот цикл, пришлось бы сильно попариться, поэтому решили не исправлять эту утечку, тем более, что она не часто проявлялась. Вот тебе и хваленые сборщики мусора...

timefim

В общем, как я уже сказал - это всего лишь одна из фич языка:

Да это фича которая делает язык более низкоуровневым.
если ты хочешь контролировать
Не хочешь, а вынужден.

agent007new

Не хочешь, а вынужден.
Благодаря всяким умным указателям можно вообще не париться об освобождении ресурсов - они будут сами освобождаться в ЧЕТКО определенный момент, а не когда луна войдет в нужную фазу.
typedef shared_ptr<MyClass> MyClassPtr;
MyClassPtr obj(new MyClass);
obj->DoSmth;
Такая же штука получается, как в жабе, шарпе и питоне. Только, если тебе нужно, то можно спуститься на более низкий уровень и подправить все напильником, если такой вариант по какой-нибудь причине не подходит

timefim

Благодаря всяким умным указателям можно вообще не париться об освобождении ресурсов
Прямо таки совсем?

klyv

Если ты ничего кроме цепепе/цешарпа/бидона/т.п. не юзал, то лучше помолчи ;)
кого надо знать, чтобы вступить в ваши круги?

agent007new

Прямо таки совсем?
Джавная, шарповая, питонья модели управления памятью таким механизмом покрываются полностью. Есть, правда, еще управление другими ресурсами, которое не делается автоматически в этих языках и приходится писать try-finally или using в шарпе. shared_ptr может и с этим справиться.
Например, хотим с виндовыми хэндлами работать:
typedef shared_ptr<void, &CloseHandle> HandlePtr;
HandlePtr filePtr(CreateFile
Хэндл автоматически закроется, когда он станет никому не нужен

sergeikozyr

shared_ptr убог и медленен, не надо

agent007new

shared_ptr убог и медленен, не надо
Чем он убог? Есть, конечно же, накладные расходы, но и не такой уж он медленный. Вот примерчик тут простенький состряпал на создание/удаление объектов:


void TestNative
{
clock_t begin = clock;

for (size_t i = 0; i < 10000000; ++i)
{
MyClass* p = new MyClass;
delete p;
}

clock_t end = clock;
std::cout << "Native: " << double(end - begin) / CLOCKS_PER_SEC << std::endl;
}

void TestShared
{
clock_t begin = clock;

for (size_t i = 0; i < 10000000; ++i)
{
boost::shared_ptr<MyClass> p(new MyClass;
}

clock_t end = clock;
std::cout << "Shared: " << double(end - begin) / CLOCKS_PER_SEC << std::endl;
}

MyClass имеет две реализации: совсем пустую и имеющую, некоторые данные, которые требуют инициализации:

class MyClass
{
};

class MyClass
{
public:
MyClass :
vec_(1000, 0)
{
}

private:
std::vector<int> vec_;
};

На создании пустых объектов чуть больше чем в два раза проигрывает shared_ptr:
Native: 2.296
Shared: 5.735
Сильный проигрыш? На самом деле сложно сказать. Если софтина то и делает, что создает такие объекты - может быть, но если объекты становятся сложными, то мы получаем уже такой результат:
Native: 20.656
Shared: 23.125
Т.е. всего лишь 10%

sergeikozyr

если объектов много, то плохо. Такая ситуация встречается.
У нас на работе именно из-за этого отказались от shared_ptr.

psihodog

Те же классы, те же объекты, которые определяет программист. Есть разница в их синтаксисе, способе работы, но не более. У этих языков разница в библиотеках, в конструкциях языка, из-за которых некоторые вещи делаются проще то на одном языке, то на другом.
бугога... ты не знаешь питон :smirk:

agent007new

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

psihodog

и чего нельзя сделать?

Dasar

и чего нельзя сделать?
допустим,
1) иметь средствами языка управляемую систему выведения типов.
2) иметь возможность просмотра "поведения" абстракции при конкретных условиях

klyv

управляемую систему выведения типов
что под этим подразумевается?
возможность просмотра
на каком этапе?

Dasar

что под этим подразумевается?
если в общих терминах, то:
1. есть "приемники" (например, функции которые принимают данные в определенном формате
2. есть "источники" (например, типы которые выдают данные в определенном формате
3. есть "преобразователи" (например, операторы преобразования которые переводят данные из одного формата в другой
необходимо, чтобы:
1. язык умел при передаче "источника" в "приемник" построить цепочку преобразований
2. язык умел визуализировать эту цепочку преобразований
3. язык умел решать конфликты (как в автоматическом, так и в ручном варианте) преобразований (например, когда возможно несколько преобразований)
пример (из банальных)
формат хранения прямоугольника может быть следущих видов:
1. центр + "радиусы"
2. угол + "диаметры"
3. два противоположных угла
4-6. все тоже самое нормированное: "радиусы" и "диаметры" не могут быть отрицательными, первый угол должен быть "меньше", чем второй
есть преобразования:
1->2
1->4
2->5
4->5
на входе есть прямоугольник в формате 1
его нужно передать в функцию принимающую прямоуольник в формате 5
хотение: чтобы язык автоматически преобразовал при передаче из ф.1 в ф.5
на каком этапе?
на этапе конкретизирования
на этапе debug-а

klyv

Спасибо, развёрнуто.
А это разве проблема (задача) языка, а не библиотеки?
Пример языка, это реализующего?
Имо, тут в преобразованиях всюду различные веса и пригодности вариантов, так что на уровне языка будет очень проблематично с этим разбираться.

Dasar

А это разве проблема (задача) языка, а не библиотеки
проблема в том, что на уровне библиотеки - это не решить (по крайней мере компактно и красиво)
согласен, что и в язык все такие шняги тащить - не стоит.
имхо, это должна быть либа - которая может тесно интегрироваться с языком.
Пример языка, это реализующего?
не встречал.
т.е. даже ФЯ, которые декларируют, что "преобразование - наше всё" - такое не умеют.
ps
это я все к тому, что я согласен с выше прозвучавшей мыслью - что существующие языки по возможностям одиннаковы: питон, C++, C#, Java, javascript и т.д.,
т.к. мощных вещей там все равно нет, а немощные везде сделаны примерно одиннаково.

sergeikozyr

 

data Rectangle = UnsafeRep1 Float Float Float | UnsafeRep2 Float Float Float
| UnsafeRep3 Float Float Float | .... | SafeRep1 Float Float Float | SafeRep2 Float Float Float | ...
safetize_rectange :: Rectangle -> Rectangle
safetize_rectange rectangle = case rectangle of
UnsafeRep1 a b c -> SafeRep1 ....
UnsafeRep2 a b c -> SafeRep2 ....
....
UnsafeRepN a b c -> SafeRepN ....
_ -> rectangle

это примерно?

Dasar

safetize_rectange rectangle = case rectangle of
UnsafeRep1 a b c -> SafeRep1 ....
UnsafeRep2 a b c -> SafeRep2 ....
....
UnsafeRepN a b c -> SafeRepN ....
_ -> rectangle

это примерно?
нет
преобразования должны быть независимые (в виде отдельных функций а не запиханные в одну функцию

sergeikozyr

Зачем отдельные функции? По-моему, того, что есть отдельные конструкторы, уже вполне достаточно.

Dasar

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

klyv

существующие языки по возможностям одиннаковы: питон, C++, C#, Java, javascript и т.д.
они разные хотя бы тем, что Python и JavaScript позволяют динамически изменять тип, а C++, C# и Java - нет.
или тем, что, например, Python позволяет использовать приёмы метапрограммирования, остальные - нет.

klyv

имхо, это должна быть либа - которая может тесно интегрироваться с языком.
Это разве не решается либой, которая просто активно использует reflection (в языках, где он требуется)?
Например, в C# - подцепляем все прописанные преобразования и создаём сборку, в которой быстро и просто вычисляется, из какого в какой тип надо преобразовать - и всё. Вызов типа ConvertTo<A>(b) вполне элегантно выглядит, имо.

psihodog

того что ты написал нету, да, но в питоне такое направление и не возможно, из-а duck-тайпинга
это я все к тому, что я согласен с выше прозвучавшей мыслью - что существующие языки по возможностям одиннаковы: питон, C++, C#, Java, javascript и т.д.,
"по возможностям" — в каком смысле?
если в том смысле, что "всё можно написать на ассемблере", то да.
а так — нет.
т.к. мощных вещей там все равно нет, а немощные везде сделаны примерно одиннаково.
лол, то-то c++ вытесняется ото всюду, откуда его можно вытеснить...
наверно, просто скучно стало на нём писать, решили все пересесть на язык такой же по мощности, но другой по синтаксису.

Dasar

они разные хотя бы тем, что Python и JavaScript позволяют динамически изменять тип, а C++, C# и Java - нет.
во-первых:
пример, активного использования данной фичи в больших проектах
сколько человеко-часов это, по-твоему, сэкономило?
во-вторых:
в C++, C#, Java - это делается так:

class MyDynamicObject
{
Dictionary<string, object> Storage = new Dictionary<string, object>
public object Call(string name, params object[] vals)
{
return Getter<object, object[]>)Storage[name]vals);
}
public void AddMethod(string name, Getter<object, object[]> method)
{
Storage[name] = method;
}
}

или тем, что, например, Python позволяет использовать приёмы метапрограммирования, остальные - нет.
перечисли, плиз, приемы - которые, ты относишь, к метапрограммированию.

Dasar

лол, то-то c++ вытесняется ото всюду, откуда его можно вытеснить...
наверно, просто скучно стало на нём писать, решили все пересесть на язык такой же по мощности, но другой по синтаксису.
C++ вытесняется по причинам, не относящимся к самому языку
1. слабый framework (заточенность под исходники, а не под уже собранные либы и т.д.)
2. культивирование прямой работы с памятью
3. однопроходность компилятора
4. сложный синтаксис (из-за требования совместимости с первым диалектом C)

Dasar

Это разве не решается либой, которая просто активно использует reflection (в языках, где он требуется)?
Например, в C# - подцепляем все прописанные преобразования и создаём сборку, в которой быстро и просто вычисляется, из какого в какой тип надо преобразовать - и всё. Вызов типа ConvertTo<A>(b) вполне элегантно выглядит, имо.
возможность преобразования и вид преобразования выяснится только на этапе исполнения.
а хочется на этапе компиляции

klyv

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

Dasar

"по возможностям" — в каком смысле?
если в том смысле, что "всё можно написать на ассемблере", то да.
а так — нет.
по возможностям, которые сильно влияют на следующее (в сторону уменьшения):
1. человеко-часы на разработку
2. человеко-часы на отладку
3. человеко-часы на понимание кода
4. требуемый уровень разработчика

klyv

хочется на этапе компиляции
Тогда - custom tool для нужной(ых) среды разработки, который делает тоже самое, но не на базе готовых сборок, а на базе исходников (+ необходимые сборки).

Dasar

Django, пример проекта (конечно, не без доработок напильниками) - Google.
не нашел там активного изменения объектов на лету
в кратце - возможность доработать тип (класс) на основе его объявления и требуемого поведения. а так же возможность делать это на лету.
и как при этом проверяется/гарантируется, что это не уронит все остальное?

klyv

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

Dasar

ээ... хотя бы модели - они создаются на основании объявления класса.
так это создание объекта, а не изменение его во время работы
ps
создавать объекты динамически - можно и в Java, и в C#: например, через генерацию исходника с последующей компиляцией и подгрузкой.
что, например, в том же .net активно используется даже в стандартной либе

karkar

лол, то-то c++ вытесняется ото всюду
Что интересно, именно С++ с его кастомными операторами приведения типов ближе всего к тому, что просил .

klyv

создавать объекты динамически - можно и в Java, и в C#
но это - достоинство Framework, а не языка.

psihodog

по возможностям, которые сильно влияют на следующее (в сторону уменьшения):
1. человеко-часы на разработку
2. человеко-часы на отладку
3. человеко-часы на понимание кода
не уверен, что тут прямая зависимость с высокоуровневостью.
а так, foreach намного понятнее домохозяйке, чем for (int i = 0; ...; ++i)
4. требуемый уровень разработчика
пехепе :crazy:

Dasar

а так, foreach намного понятнее домохозяйке, чем for (int i = 0; ...; ++i)
так это как раз - человеко-часы на понимание кода и на отладку

Dasar

но это - достоинство Framework, а не языка.
но это различие важно для академиков, а не для пользователей языка.

bleyman

Даркгрей просил, в частности, чтобы это всё было отлаживаемо и умопознаваемо. Плюсовые приведения работают прямо обратным образом, взять хотя бы милую привычку компилятора дефолтится в преобразование стрингов через char* (случается редко, но дичайше неприятно). А даже если тебе очень повезло и он таки ругнулся, то в том, что он тебе сказал, ты ничего не поймёшь, потому что там наверняка будет особая темплейтная магия, со всеми вытекающими.
Но. Вообще-то если вчитаться в формулировку, то становится понятно, что язык как бы практически ни при чём, в парадигме "компилятор преобразует сурс в бинарник" она попросту не решается. Советоваться с программером насчёт преобразований — это работёнка для IDE! Ну, понятно, язык тоже должен соответствовать, но без поддержки IDE ничего не получится.
Кстати, пример выглядит довольно стрёмно, в смысле что навевает мысли о наколенных поделках высоколобых академиков. Я когда-то читал одну весьма познавательную статью в защиту статик тайпинга (причём именно с тэгами, а не duck в которой был гораздо лучше пример: эскейпнутые и неэскейпнутые строки в любом вебприложении. Если оно ещё и с sql работает, то эскейпов вообще получается много типов - эскейпнутые для хтмл, для урл, для sql. Вот, реальный пример, когда автоматическая проверка типов избавляет от чудовищного геморроя, а если б ещё и автоматическое приведение было...
Ещё пример - реализация пользовательских штук, похожих на шарповые nullable. Я даже когда-то находил все места в спецификации, где лежит специальный синтаксический сахар для них, его много! Что наводит мгновенно на следующую мысль: это ж монада, вообще-то. Я хаскеля не знаю, там как, монады умеют автоматически lift делать? Если да, то нафига emacs писал какую-то фигню с алгебраическими типами?

karkar

Мне вообще кажется, что неявные преобразования типов - зло и источник багов.
Но уж если их хочется, то С++ их дает. А многие другие "высокоуровневые" языки - нет. Только и всего.
В прынцыпе, если все виды прямоугольников будут иметь общий набор методов (например, у всех будут функции возврата ширины и площади то duck typing позволит их везде использовать без приведений.

klyv

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