Магические методы
Что мне никогда не нравилось в Пайтоне, так это «магические» методы и свойства. Сейчас их существует за сотню:
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».
В Ruby так и сделано, и это действительно интуитивно понятнее.
Комментарий для kuntashov.moikrug.ru:
Я почему-то подозревал, что в Руби так же. То ли где-то видел и в памяти отложилось, то ли это какое-то ожидание интуитивное от языка. Поискал утром в Википедии, не увидел подходящих примеров, не стал глубже смотреть.
Комментарий для Евгения Степанищева:
Ключевые слова: ruby operator expressions.
Вот здесь коротко: http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html#s1
__new__ всё же не совсем конструктор объекта, это скорее «конструктор» мета-класса, т. е. того инстанцией чего будет текущий объект. В сравнении __new__ возвращает инстанцию класса, а __init__ уже с ней работает и не требует возврата.
Комментарий для rembish.livejournal.com:
В данном контексте это лишняя подробность.
Это еще что, вот в Хаскелле, говорят, можно вообще свои операторы вроде +++ придумывать. Хотя перегрузка операций для не-чисел — очень спорная вещь, так как если смотреть на код, непонятно с ходу, какой именно метод там вызывается.
Комментарий для egorinsk:
Это просто другая запись для вызова какого-то метода. Синтаксический сахар. Когда я вижу object.something() я тоже не знаю что реализует something, могу только догадываться по названию. С этой точки зрения obj1+obj2 ничем не хуже (скорее лучше), чем obj1.add(obj2).
А нельзя запилить какой файл с аллиасами?
Комментарий для hshhhhh.name:
М? Что?
Комментарий для Евгения Степанищева:
ну, в смысле, что-нибудь типа файла:
function __>__ () {
return __gt__();
}
Комментарий для hshhhhh.name:
Нет, так работать не будет.
Во-первых, будет ошибка синтаксиса (имена функций и методов не могут в языке содержать такие символы).
Во-вторых, это тут функции, а надо методы.
Во время изучения языка вся эта сотня магических методов не нужна, поэтому и приходится учить последовательно понемногу. И, кажется, перечисленные методы вполне интуитивны, чтобы их запомнить, когда дело доходит до них.
Еще есть синтаксическая проблема: поскольку все функции являются объектами, название метода (функции) не должно ломать синтаксис не только в его определении, но и само по себе. А с точки зрения синтаксиса, __<__, +self и т. п. не могут являться атомарными токенами. Если разрешить называть метод «<», но запретить вызывать его как <(obj1, obj2), на мой взгляд, проигрыш в интуитивности будет гораздо больше.
Ну и ты сам говоришь, что магических методов больше сотни, а переименовать предлагаешь лишь малую часть, так что это не решит проблему.
Комментарий для fulc.ru:
Я просмотрел эту сотню бегло. Знаешь, по одиночке они более-менее интуитивны, вместе — нет.
И не должны. Атомарным токеном должно являеться «<», «+» и прочие названия (в этом контексте) методов. «+self» тут два токена — название метода и название переменной, куда текущий экземпляр кладётся.
В Пайтоне уже есть место, которое работает так же, ничего живём. Даже специальный модуль есть — operator.
Переименовать предлагаю большую часть. Большая часть относится как раз к операциям.
Комментарий для egorinsk:
В хаскеле ещё интереснее — любую функцию можно вызывать инфиксно. Т. е. можно «foo a b», а можно «a ’foo’ b» :) и наоборот: «(+) a b». Кавычки только там другие,в телефоне нету:)
Комментарий для Евгения Степанищева:
Это какое?
Комментарий для fulc.ru:
Модуль operator.