Магические методы

Что мне никогда не нравилось в Пайтоне, так это «магические» методы и свойства. Сейчас их существует за сотню:
bolk@Bolk ~  $ wget -O- http://docs.python.org/reference/datamodel.html 2>&- | egrep -o '__(\w+)__' | sort -u | wc -l
     108
Я, даже если очень постараюсь, вряд ли вспомню хотя бы половину. Всё «магическое» в Пайтоне начинается и заканчивается двумя подчёркиваниями, например, если сменить знак у объекта (сделать „-something“), то Пайтон попытается вызвать магический метод «__neg__». В более распространнённом ПХП всё примерно так же, но «магических» методов сильно меньше, их я уже помню на память все, но и возможности гораздо уже.

Запомнить все эти методы, наверное, реально при помощи тщательной зубрёжки, но сделать это естетственно, во время изучения языка, нереально, по моему мнению. Причина — неинтуитивность. Я давно высказывался на тему, почему хотя бы не расширить синтаксис и некоторые методы не разрешить называть как операции, то есть «/», «+», «[]» и так далее, смутно вспоминая, что в Си++, кажется, так и сделано.

Оказывается, так в точности сделано в языке «Скала»:
trait Ord{
    def < (that:Any):Boolean
    def<=(that:Any):Boolean = (this < that) || (this == that)
    def> (that:Any):Boolean = !(this <= that)
    def>=(that:Any):Boolean = !(this < that)
}
Это гораздо проще выучить, изучая язык, чем «__lt__», «__le__», «__gt__», «__ge__» (впрочем, когда перечисляешь в ряд несколько конструкций, кажется что ничего страшного в этом нет, но надо держать в голове, что их больше сотни).

У некоторых методов название упрощать не нужно, например «__unicode__» (преобразование к юникодной строке) всё равно дёргается стоит вызвать unicode(something) или «__del__» (деструктор) вызывается, в частности, если сделать «del something» (если ссылок больше нет). Они уже содержат название операции, просто оно буквенное. Есть методы, которые вряд ли вообще можно как-то проще назвать, например «__new__» и «__init__» — названия конструкторов для «новых» и «старых» объектов Пайтона.

Наверняка есть часть, которую понятнее не назовёшь. На ум сразу приходит метод «__hash__», думаю есть и ещё.

Но, бо́льшую часть, мне бы хотелось именовать как-то понятнее. Причём, вполне можно предложить синтаксис для левостоящих и правостоящих объектов, что-то вроде «def self+» и «def +self».
12 марта 2012 08:16

Александр Кунташов (kuntashov.moikrug.ru)
12 марта 2012, 09:38

В Ruby так и сделано, и это действительно интуитивно понятнее.

bolk (bolknote.ru)
12 марта 2012, 09:45, ответ предназначен Александр Кунташов (kuntashov.moikrug.ru):

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

Александр Кунташов (kuntashov.moikrug.ru)
12 марта 2012, 09:59, ответ предназначен bolk (bolknote.ru):

Ключевые слова: ruby operator expressions.
Вот здесь коротко: http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#s1

pan Ramon (rembish.livejournal.com)
12 марта 2012, 10:03

__new__ всё же не совсем конструктор объекта, это скорее "конструктор" мета-класса, т.е. того инстанцией чего будет текущий объект. В сравнении __new__ возвращает инстанцию класса, а __init__ уже с ней работает и не требует возврата.

bolk (bolknote.ru)
12 марта 2012, 10:10, ответ предназначен pan Ramon (rembish.livejournal.com):

В данном контексте это лишняя подробность.

egorinsk (инкогнито)
12 марта 2012, 10:22

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

bolk (bolknote.ru)
12 марта 2012, 10:39, ответ предназначен egorinsk

Это просто другая запись для вызова какого-то метода. Синтаксический сахар. Когда я вижу object.something() я тоже не знаю что реализует something, могу только догадываться по названию. С этой точки зрения obj1+obj2 ничем не хуже (скорее лучше), чем obj1.add(obj2).

hshhhhh (hshhhhh.name)
12 марта 2012, 12:42

А нельзя запилить какой файл с аллиасами?

bolk (bolknote.ru)
12 марта 2012, 13:14, ответ предназначен hshhhhh (hshhhhh.name):

М? Что?

hshhhhh (hshhhhh.name)
12 марта 2012, 19:40, ответ предназначен bolk (bolknote.ru):

ну, в смысле, что-нибудь типа файла:
function __>__ () {
return __gt__();
}

bolk (bolknote.ru)
12 марта 2012, 20:50, ответ предназначен hshhhhh (hshhhhh.name):

Нет, так работать не будет.

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

Fulcrum (fulc.ru)
13 марта 2012, 04:34

Это гораздо проще выучить, изучая язык, чем «__lt__», «__le__», «__gt__», «__ge__»
Во время изучения языка вся эта сотня магических методов не нужна, поэтому и приходится учить последовательно понемногу. И, кажется, перечисленные методы вполне интуитивны, чтобы их запомнить, когда дело доходит до них.

Еще есть синтаксическая проблема: поскольку все функции являются объектами, название метода (функции) не должно ломать синтаксис не только в его определении, но и само по себе. А с точки зрения синтаксиса, __<__, +self и т. п. не могут являться атомарными токенами. Если разрешить называть метод "<", но запретить вызывать его как <(obj1, obj2), на мой взгляд, проигрыш в интуитивности будет гораздо больше.

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

bolk (bolknote.ru)
13 марта 2012, 07:41, ответ предназначен Fulcrum (fulc.ru):

И, кажется, перечисленные методы вполне интуитивны, чтобы их запомнить, когда дело доходит до них.
Я просмотрел эту сотню бегло. Знаешь, по одиночке они более-менее интуитивны, вместе — нет.
А с точки зрения синтаксиса, __<__, +self и т. п. не могут являться атомарными токенами.
И не должны. Атомарным токеном должно являеться «<», «+» и прочие названия (в этом контексте) методов. «+self» тут два токена — название метода и название переменной, куда текущий экземпляр кладётся.
Если разрешить называть метод „<“, но запретить вызывать его как <(obj1, obj2), на мой взгляд, проигрыш в интуитивности будет гораздо больше.
В Пайтоне уже есть место, которое работает так же, ничего живём. Даже специальный модуль есть — operator.
Ну и ты сам говоришь, что магических методов больше сотни, а переименовать предлагаешь лишь малую часть, так что это не решит проблему.
Переименовать предлагаю большую часть. Большая часть относится как раз к операциям.

desh (инкогнито)
14 марта 2012, 00:06, ответ предназначен egorinsk

В хаскеле ещё интереснее - любую функцию можно вызывать инфиксно. Т.е. можно "foo a b", а можно "a 'foo' b" :) и наоборот: "(+) a b". Кавычки только там другие,в телефоне нету:)

Fulcrum (fulc.ru)
20 марта 2012, 21:45, ответ предназначен bolk (bolknote.ru):

> Если разрешить называть метод „<“, но запретить вызывать его как <(obj1, obj2), на мой взгляд, проигрыш в интуитивности будет гораздо больше.
В Пайтоне уже есть место, которое работает так же, ничего живём.
Это какое?

bolk (bolknote.ru)
20 марта 2012, 22:46, ответ предназначен Fulcrum (fulc.ru):

Модуль operator.

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)