LINUX.ORG.RU

Изящество и неловкость Python


0

0

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

>>> Подробности

Ответ на: комментарий от r

r, ты похож на geek'a в топиках о кде. Твой новый ник PyGeek.

anonymous
()
Ответ на: комментарий от r

> При чем тут ява? Я и без вас ей скажу.

Ну, ей мы и сами уже сказали :) но почему бы не повторить? :D

>>__init__ - это вполне нормальный конструктор.

>Только с вездесущим селфом и раковым именем.

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

> Что мешало сделать как в жабаскрипте?

ХЗ, я не разрабатываю языки. Javascript намного позже Питона появился, ЕМНИП.

tailgunner ★★★★★
()
Ответ на: комментарий от r

Все тот анонимус с this.

Во первых способ A.method(instance, *args) --- не извращение, а вполне обычный способ вызова функции.

Например, надо обойти что--нибудь, у чего есть prev() и next() метод.

def count_falses(first_elem, func): ..бла бла бла ..elem = func(elem) ..бла бла бла

тогда легко получаются count_falses(instance, Storage.next) и count_falses(instance, Storage.prev). Я прав, если предположу, что в c# придется заводить флаг "направление обхода"?

> Только с вездесущим селфом и раковым именем.

Просто соглашение. У питона (особенно до 2.4), были/есть более серьезные проблемы с конструкторами, чем имя.

Зачем нужен селф легко можно показать на примере.

Если надо расширить класс или экземпляр класса на лету (а если мы занимаемся метапрограммированием, то это надо делать достаточно часто, мы не задумываясь говорим:

def method1(self, *arg): pass def method2(self, *arg): pass

class C1: pass class C2: pass class C3: pass

C1.some_method = method1 C2.some_method = method2 C3.x_method = method2 C3.y_method = method1

Обычный метод. В object pascal есть два типа функций: функции и классовые функции. В результате, если надо вынести функцию из класса, ее приходится менять.

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

> ДА уж особенно когда почумуто способ вызов имеет разный синтаксис в зависимости от места вызова - внутри класса и снаружи. Замечательно. Что мешало сделать как в жабаскрипте?

Тем, что питон --- это не ECMAScript. На самом деле мне кажется, что ecmascript --- это один из самых крутых языков нашего времени. Для меня его губит то, что большинство тех, кто пишет на нем рассуждают о браузер и их DOM. Я, блин, хочу использовать его как stand--alone/embedded язык. Ага, щаз.

anonymous
()
Ответ на: комментарий от r

Модераторы, удалите, плиз, предыдущее сообщение.

Все тот анонимус с this.

Во первых способ A.method(instance, *args) --- не извращение, а вполне обычный способ вызова функции.

Например, надо обойти что--нибудь, у чего есть prev() и next() метод.

def count_falses(first_elem, func):
..бла бла бла
..elem = func(elem)
..бла бла бла

тогда легко получаются count_falses(instance, Storage.next) и count_falses(instance, Storage.prev). Я прав, если предположу, что в c# придется заводить флаг "направление обхода"?

> Только с вездесущим селфом и раковым именем.

Просто соглашение. У питона (особенно до 2.4), были/есть более серьезные проблемы с конструкторами, чем имя.

Зачем нужен селф легко можно показать на примере.

Если надо расширить класс или экземпляр класса на лету (а если мы занимаемся метапрограммированием, то это надо делать достаточно часто, мы не задумываясь говорим:

def method1(self, *arg): pass
def method2(self, *arg): pass

class C1: pass
class C2: pass
class C3: pass

C1.some_method = method1
C2.some_method = method2
C3.x_method = method2
C3.y_method = method1

Обычный метод. В object pascal есть два типа функций: функции и классовые функции. В результате, если надо вынести функцию из класса,
ее приходится менять.

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

> ДА уж особенно когда почумуто способ вызов имеет разный синтаксис в зависимости от места вызова - внутри класса и снаружи. Замечательно. Что мешало сделать как в жабаскрипте?

Тем, что питон --- это не ECMAScript. На самом деле мне кажется, что ecmascript --- это один из самых крутых языков нашего времени. Для меня его губит то, что большинство тех, кто пишет на нем рассуждают о браузер и их DOM. Я, блин, хочу использовать его как stand--alone/embedded язык. Ага, щаз.

anonymous
()
Ответ на: комментарий от Joe_Bishop

>Популярность его обусловенна иррациональными причинами.

Хм. А кто был лучше его 20 лет назад? :) Или "исторические причины" уже == "иррациональные"? :D

KRoN73 ★★★★★
()
Ответ на: комментарий от tailgunner

> и, в общем, не работает - не освобождает наборы объектов с циклическими ссылками.

это да. Прийдётся быть чуть аккуратнее и иногда использовать weak. В пёрле и ECMAScript то же самое. Или применить тот подход, что сделан в питоне. Но зато поведение программы будет более предсказуемым, что для десктопа очень важно.

> Vala - это от слова valasiped.

действительности не соответствует. Аналогов нет. В чём недостатки D я описал. Кроме того, по фичам вала уже сейчас догнала D. Через год-полгода она точно превзойдёт его.

Joe_Bishop
()
Ответ на: комментарий от KRoN73

> Хм. А кто был лучше его 20 лет назад? :) Или "исторические причины" уже == "иррациональные"? :D

20 лет назад цепепе был очень убогим, даже более убогим чем сейчас. А кто был лучше его? Да та же ада, например. Разработка на ней куда быстрее.

Joe_Bishop
()
Ответ на: комментарий от Joe_Bishop

> В пёрле и ECMAScript то же самое.

А что, Пёрл - это уже типа эталон и объект подражания?

> Аналогов нет.

И не нужно

> В чём недостатки D я описал.

Сорвал все покровы одним предложением, Молодец,

> Кроме того, по фичам вала уже сейчас догнала D.

В ней уже есть шаблоны? Средства метапрограммирования? Она уже кроссплатформенна?

tailgunner ★★★★★
()
Ответ на: комментарий от Joe_Bishop

> та же ада, например. Разработка на ней куда быстрее.

Что-то мне подсказывает, что ты не знаком ни с тогдашней Адой, ни с современной.

tailgunner ★★★★★
()
Ответ на: комментарий от Joe_Bishop

>А кто был лучше его? Да та же ада, например.

Вот так "теоретики" и палятся... :)

KRoN73 ★★★★★
()
Ответ на: комментарий от tailgunner

> В ней уже есть шаблоны?

есть Generics. Не совсем то по сути, но по работе примерно соответствует. Метапрограммирование? Зачем? Чтобы делать то, для чего язык не предназначен, а потом разгребать километровые листинги об ошибках при компиляции? Зачем это нужно? Типа, писать в функциональном стиле?

> Она уже кроссплатформенна?

это не нужно

Joe_Bishop
()
Ответ на: комментарий от tailgunner

> Что-то мне подсказывает, что ты не знаком ни с тогдашней Адой, ни с современной.

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

Joe_Bishop
()
Ответ на: комментарий от tailgunner

> Сорвал все покровы одним предложением, Молодец,

по ссылкам не ходим. то что оппонент написал не читаем? Короче, вот список недостатков: 1) Сборщик мусора вносит непредсказуемость в работу программы и провоцирует излишнее использование памяти. 2) Сложность при использовании кода в других языках. 3) Излишне сложный синтаксис.

Joe_Bishop
()
Ответ на: комментарий от Joe_Bishop

> Метапрограммирование? Зачем?

Ты сказал, что Vala догнала D по фичам. А выходит, что нифига.

>> Она уже кроссплатформенна?

>это не нужно

Говори за себя.

>> Что-то мне подсказывает, что ты не знаком ни с тогдашней Адой, ни с современной.

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

Как же так? o_O Совсем недавно ты сказал, что Ада была лучше Си++.

tailgunner ★★★★★
()
Ответ на: комментарий от Joe_Bishop

> по ссылкам не ходим. то что оппонент написал не читаем

ну кто бы уж говорил. а?

> Короче, вот список недостатков: 1) Сборщик мусора вносит непредсказуемость в работу программы и провоцирует излишнее спользование памяти. 2) Сложность при использовании кода в других языках. 3) Излишне сложный синтаксис.

Это и называется "одним предложением". Поясняю: ты не пробовал D в деле (думаю, и Vala тоже), ты даже со спецификациями нормально не ознакомился. но делаешь какие-то выводы. С этой точки зрения особенно умиляет пункт 1. Ты вообще хоть что-нибудь знаешь об алгоритмах сборки мусора, использованных в Vala и Tango, за исключением "в Vala используется reference-counting"?

tailgunner ★★★★★
()
Ответ на: комментарий от Joe_Bishop

> неа, сборщик мусора всё портит, будет жрать память и временами подтормаживать.

По факту - не жрёт и не тормозит.

> К тому же, у D, имхо, немного переусложнённый синтаксис и сложности с использованием его кода в других языках.

Сложного синтаксиса не заметил. По сравнению с крестами - вообще благолепие. Использование в других языках... ну это конечно вопрос, хотя вроде pyd уже что-то умеет.

yk4ever
()
Ответ на: комментарий от r

> Как это меняет то что self в питоне не нужен? Если бы его не було питон бы нисколько не пострадал.

Это нужно для концептуальной чистоты. Метод - просто обёртка над функцией.

yk4ever
()
Ответ на: комментарий от Joe_Bishop

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

Это важно для систем реального времени. На десктопе оно как бы пофиг, там важнее дешевизна разработки.

yk4ever
()
Ответ на: комментарий от Joe_Bishop

> это не нужно

Это некроссплатформенное "не нужно".

yk4ever
()
Ответ на: комментарий от anonymous

>A.method(instance, *args) --- не извращение, а вполне обычный способ вызова функции.

В то время как instance имеет тот же метод которому не надо его передаввать? Извращение.

>Например, надо обойти что--нибудь, у чего есть prev() и next() метод.

А ты не заметил что этот сount_falses при этом не метод этого чего-то и первый агрумент у него не селф, а обычный аргумент? Можешь поменять местами.


> Я прав, если предположу, что в c# придется заводить флаг "направление обхода"?

В любом языке где функция first class object можно это сделать.

При чем тут self? Ты вкус огурцов на примере арбузов доказывать собрался?

>Обычный метод.

Жабаскрипт позволяет делать то же самое без заката солнца в ручную.

function C1() {};
function C2() {};
function C3() {};

function method(arg) {
return this.value + arg;
}

C1.prototype.f1 = method;
C2.prototype.f2 = method;
C3.prototype.f3 = method;

>.В питоне если функция не трогает внутренних имен, ее можно двигать "туда--сюда" не изменяя ее вообще.

Если функция не трогает состояние класса то делаеть ей в этом классе нечего.

> Я, блин, хочу использовать его как stand--alone/embedded язык. Ага, щаз.

http://developer.mozilla.org/en/docs/Category:SpiderMonkey
http://developer.mozilla.org/en/docs/Rhino (я пользуюсь под жабу для написания плугинов).
http://developer.mozilla.org/en/docs/Category:Tamarin

Када допишут Tamarin я надеюсь будет нормальный standalone runtime.

r ★★★★★
()
Ответ на: комментарий от Joe_Bishop

>Сборщик мусора вносит непредсказуемость в работу программы и провоцирует излишнее использование памяти.

А ты что - уже научился предсказывать с какой скоростью релизится память на delete для дерева объектов неопределенного размера?

r ★★★★★
()
Ответ на: комментарий от yk4ever

>Это нужно для концептуальной чистоты. Метод - просто обёртка над функцией.

Для концептуальной чистоты надо было отдать это компилятору как блюстителю концептуальной чистоты ;-p

r ★★★★★
()
Ответ на: комментарий от r

протормозил - поправлюсь:

>тогда легко получаются count_falses(instance, Storage.next)

так же легко получается

def count_falses(m):
...:m()

count_falses(instance.next)

r ★★★★★
()
Ответ на: комментарий от r

> Для концептуальной чистоты надо было отдать это компилятору как блюстителю концептуальной чистоты ;-p

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

Нет, я, конечно, согласен, что писать всюду self - несколько утомительно. Однако это не настолько серьёзная проблема, чтобы так сильно из-за неё переживать. Если уж совсем невмоготу - перелазьте под Ruby, хотя я его заморочек не одобряю.

Чего там неэстетичного все видят в питоновских __спецназваниях__ - не понимаю. По-моему, вполне красиво. Даже вон в пятом пыхпыхе __init__ украли под видом __construct. Конструктор, одноимённый классу - есть зло, конструктор должно быть видно сразу. Просто "init" - скучно.

yk4ever
()

Вспомнил по теме "неловкость"...

Объясните мне логику того, кто придумал писать

",".join(array)

вместо array.join(",")

:)

KRoN73 ★★★★★
()
Ответ на: комментарий от r

Тот же анономус.

так же легко получается

def count_falses(m): ....m()

Это не то же самое, что я писал. Тот же пример, но подробнее.

def count_falses(start_elem, func): ....next = func(start_elem) ....while next != start_elem: ........бла бла бла ........next = func(next) ....бла бла бла

> Када допишут Tamarin я надеюсь будет нормальный standalone runtime.

Я знаю, что есть stand--alone. Не помню, как называется, но один я пробовал. Дело не в том. Если я пишу на питоне, у меня нет проблем с библиотеками. Я знаю, что открывая доку я не увижу ненужного мне способа обмануть ie.

anonymous
()
Ответ на: комментарий от KRoN73

> Объясните мне логику того, кто придумал писать

> ",".join(array)

def simple_generator():
....for i in range(10):
........yield 'str %3d' % i

print ','.join(simple_generator)

anonymous
()
Ответ на: комментарий от r

Тот же анономус. И я опять забыл, что если капчу ввести неправильно, то user line break сбрасывается.

> так же легко получается

> def count_falses(m):
> ....m()

Это не то же самое, что я писал. Тот же пример, но подробнее.

def count_falses(start_elem, func):
....next = func(start_elem)
....while next != start_elem:
........бла бла бла
........next = func(next)
....бла бла бла

> Када допишут Tamarin я надеюсь будет нормальный standalone runtime.

Я знаю, что есть stand--alone. Не помню, как называется, но один я пробовал. Дело не в том. Если я пишу на питоне, у меня нет проблем с библиотеками. Я знаю, что открывая доку я не увижу ненужного мне способа обмануть ie.

anonymous
()
Ответ на: комментарий от yk4ever

>Питон стремится избежать магии. Параметры в функцию должны передаваться явно.

В таком случае - не получилось. __init__ вызывается неявно, параметр туда передается неявно, в любой метод он передается неявно. Магия.

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

Я и не говорю что она супер серьезная. Все началось с эстетики:) а переросло во флейм:))

r ★★★★★
()
Ответ на: комментарий от anonymous

> Это не то же самое, что я писал. Тот же пример, но подробнее. 

Тока не говорите что нижеприведенное концептуально не лучше.

class L:
    def __init__(self,v,n=None):
        self.v = v
        self.n = n
    def next(self):
        return self.n

l = L(1,L(2,L(3,L(4))))

def walk(l,m):
    x = l
    while x != None:
        print x.v
        x = m(x)


walk(l, lambda x: x.next())

r ★★★★★
()
Ответ на: комментарий от r

> Тока не говорите что нижеприведенное концептуально не лучше.

Концептуально не хуже. Но зачем добавлять ненужную функцию?

Ваш пример, имхо, лучше выглядит в виде:

walk(l, L.next)

Хотя я понимаю, что не везде можно провести такую замену.

anonymous
()
Ответ на: комментарий от anonymous

>Но зачем добавлять ненужную функцию?

Она не ненужная. Обычная лямбда. walk - обычная функция высшего порядка. Все ясно как день. А не мистическое шаманство с именами и необязательными скрытыми аргументами указывающими на экземляр. Питон вроде как задумывался как 'читаемый' язык. В случае наличия self и аргументов со значениями по умолчанию глядя на такой вызов приходится заниматься исследовательской деятельности в области disambiguation когда декларированных аргументов 6, а вызывавется функция с 3-мя.

типа
class X:
...:def a(self, a,b,c="a", d="3"):....


xx.a(x,y,z);

что тут вызывается? Ведь xx может быть как xx = X() так и xx = X.

Явно тут Гвидо перемудрил.

r ★★★★★
()
Ответ на: комментарий от r

> xx.a(x,y,z);

> что тут вызывается? Ведь xx может быть как xx = X() так и xx = X.

Так как мы хорошие дети, читали и следуем PEP8, то, конечно

a, b, c = x, y, z

anonymous
()
Ответ на: комментарий от r

> Из чего это следует?

Вообще не из чего. Но все--таки если код хороший, то он следует PEP 8.

В PEP 8 написано:

> Class Names

> Almost without exception, class names use the CapWords convention. Classes for internal use have a leading underscore in addition.

anonymous
()
Ответ на: комментарий от anonymous

>В PEP 8 написано:

А переменные которым присвоены классы - тоже большими буквами?

class C:
....pass

c = C
d = C
e = C

??

r ★★★★★
()
Ответ на: комментарий от r

> А переменные которым присвоены классы - тоже большими буквами?

Вообще это просто алиас на класс. Зачем его делать с маленькой буквы?

anonymous
()
Ответ на: комментарий от anonymous

>Зачем его делать с маленькой буквы?

А если это параметр переданный в функцию переданный в функцию переданный в функцию..... ?

r ★★★★★
()
Ответ на: комментарий от r

> __init__ вызывается неявно

Это можно рассматривать как часть классметода __call__, определённого для класса "объект".

> параметр туда передается неявно

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

> Магия.

Как видим, никакой магии. Сплошная концептуальная чистота. Объектная модель Питона - вообще одна из лучших из существующих в природе.

yk4ever
()
Ответ на: комментарий от r

> Явно тут Гвидо перемудрил.

Слышал что для Гвидо кто-то перевёл что за ересь ты тут на Питон гонишь. Гугль помог найти твой IP и спонсировал F16. Гвидо летит к тебе.

"Страх перед смертью страшнее самой смерти" (c) С.Сигал

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.