Похоже, что объединение Python фокусируется не на элементах, которые нужно объединить, а на символе по сравнению с Ruby или Smalltalk по соображениям дизайна?

9

Я думал, что один из краеугольных камней ООП состоит в том, что у нас есть объекты, с которыми мы имеем дело, и затем мы отправляем им сообщения.

Поэтому может показаться естественным, что у меня есть коллекция предметов, и мне нужно поместить их в одну строку, чтобы сделать это:

  ["x", "o", "o"].join(" | ")    # joining a tic-tac-toe row in Ruby

(Smalltalk делает это так же). Это " | "в некотором роде рассматривается как аргумент, один из признаков того, как присоединиться к нему. Может быть " "и так, если игровое поле будет проще. Таким образом, объединяющий элемент " | "не особенно интересует нас - это не основные объекты в программе, которые имеют особое значение или значение.

Если Python делает это с помощью

  " | ".join(["x", "o", "o"])

Это действительно несколько странно, что мы почти чувствуем, что мы передаем сообщение аргументу, чтобы сказать аргумент о чем-то. Может, Python более процедурный? Сказать, чтобы соединительная строка выполнила какой-то долг для нас?

Это для того, чтобы сохранить реализацию, чтобы нам не приходилось определять joinдля каждого класса коллекции, который у нас есть? Но не правда ли, что мы также можем просто написать один раз для любого класса коллекции, например для Ruby:

module Enumerable
  def my_join(joiner)
    self.inject {|a,b| a.to_s + joiner + b.to_s}
  end
end

(что-то вроде этого, вызывая to_sкаждый элемент, полагаясь на то, что to_sкаждый класс делает свое дело, преобразовывает в строку, а затем объединяет их). Таким образом, нам не нужно реализовывать для каждого из String, Hash или Set или любого другого класса коллекции, который у нас есть.

Или Python вне права не идет по пути ООП? Он использует len("abc")и type([])вместо "abc".len()или [].type()даже в Python3 тоже кажется. Питон делает это таким образом по причине дизайна?

nonopolarity
источник
7
Из Дзэн Питона : «Должен быть один - и, желательно, только один - очевидный способ сделать это. Хотя этот способ может быть неочевидным сначала, если вы не голландец».
kdgregory
2
В одной форме коллекция знает, как преобразовать себя в строку с разделителем, в другой строка знает, как объединить коллекцию, используя себя в качестве разделителя. Они оба объектно-ориентированы, но меняют тему и объект глагола.
kdgregory
Maybe Python is more procedural?Python был процедурным языком с несколькими функциональными дополнениями («Python приобрел lambda, redu (), filter () и map (), любезно предоставленный хакером Lisp, который пропустил их и представил рабочие исправления») до тех пор, пока что-то не появится в версии 2. Это было примерно через полтора десятилетия после того, как над ним впервые работали.
1
И даже сегодня Python даже не пытается быть языком ООП, это полностью мультипарадигма.
Как и C ++, Python является языком, который позволяет ООП. Это не то же самое, что язык ООП, такой как Java или Smalltalk.
Gort the Robot

Ответы:

9

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

Армин Роначер говорит это лучше меня:

http://lucumr.pocoo.org/2011/7/9/python-and-pola/#seemingly-inverse-logic

«Представьте, что Python не будет работать таким образом. Сначала вам нужно будет преобразовать итерируемое в фактический список, чтобы преобразовать его в строку. Теперь люди из Ruby будут утверждать, что Ruby решает эту проблему путем смешивания в модулях, и они, безусловно, правы, что это это вариант. Но это разумное дизайнерское решение на языке, которое имеет много последствий. Python поощряет слабую связь, имея эти протоколы, где фактические реализации могут быть в другом месте. Один объект является итеративным, другая часть в системе знает, как его сделать в строку ".

Скудный Роджер
источник
1
OP пытается решить эту проблему с помощью module Enumerateраздела, но Python не работает таким образом, для всех итераторов не существует единого суперкласса, в который можно было бы поместить этот метод.
Я тоже пробовал в Ruby 2.0 ... Hashи на Stringсамом деле у меня нет класса коллекции как суперкласса ... их суперкласс просто Object. Таким образом, эти два класса просто полагаются на наличие Enumerable mixin ... что-то, как я понимаю, как интерфейс, позволяющий установить набор поведений коллекции
неполярность
Так что это в значительной степени является ограничением того факта, что «итерируемый» - это не класс или что-то с реальным кодом, а скорее шаблон печатания утки? Альтернативно, это просто потому, что Python хотел быть настолько общим, чтобы иметь возможность работать с любой коллекцией с той же реализацией (тогда как многие другие стандартные библиотеки просто реализовали бы ее для каждой коллекции, если она действительно применяется к этой коллекции).
Кат