Myślałem, że jednym z podstawowych elementów OOP jest to, że mamy przedmioty, którymi jesteśmy zainteresowani, a następnie wysyłamy do nich wiadomości.
Może więc wydawać się naturalne, że mam kolekcję przedmiotów i muszę je ułożyć w jeden sznurek, aby to zrobić:
["x", "o", "o"].join(" | ") # joining a tic-tac-toe row in Ruby
(Smalltalk robi to w ten sam sposób). " | "
Jest w jakiś sposób traktowane jako argument, jeden znak, jak się do niej przyłączyć. Może być " "
też, jeśli plansza ma być prostsza. Zatem element łączący " | "
nie jest czymś, co szczególnie nas interesuje - nie są to główne obiekty w programie, które mają szczególne znaczenie lub znaczenie.
Jeśli Python robi to za pomocą
" | ".join(["x", "o", "o"])
To trochę dziwne, że prawie czujemy, że przekazujemy argument do argumentu, aby o tym powiedzieć. Może Python jest bardziej proceduralny? Powiedzieć łączącemu łańcuchowi, aby wykonał dla nas jakiś obowiązek?
Czy ma to zapisać implementację, abyśmy nie musieli definiować join
dla każdej klasy kolekcji, którą mamy? Ale czy nie jest prawdą, że możemy napisać tylko raz dla dowolnej klasy kolekcji, na przykład w Ruby:
module Enumerable
def my_join(joiner)
self.inject {|a,b| a.to_s + joiner + b.to_s}
end
end
(coś w tym stylu, wzywając to_s
każdy element, polegając na to_s
każdej klasie, aby wykonać swoją własną rzecz, przekonwertować na ciąg, a następnie połączyć je). Zatem nie musimy implementować dla każdej String, Hash, Set, ani żadnej innej klasy kolekcji, którą mamy.
A może Python się nie zgadza? Używa len("abc")
i wydaje się, że type([])
zamiast Python3, "abc".len()
a [].type()
nawet. Czy Python robi to w ten sposób z powodów projektowych?
źródło
Maybe Python is more procedural?
Python był językiem proceduralnym z kilkoma dodatkami funkcjonalnymi („Python nabył lambda, redukcję (), filter () i map (), dzięki uprzejmości hakera Lisp, który za nimi tęsknił i przesłał łaty robocze”), dopóki coś nie wydaje się być gdzieś w wersji 2. To było około półtorej dekady po pierwszej pracy.Odpowiedzi:
Pythona przyłączenia jest przeznaczony do pracy na dowolnym iterable . Oznacza to, że projektanci musieli zdecydować, gdzie go umieścić. Ponieważ działa na więcej niż tylko listach, ale zawsze wymaga (separatora) i zwraca ciąg znaków, postanowili włączyć go do typu ciągu.
Armin Ronacher mówi to lepiej niż ja:
http://lucumr.pocoo.org/2011/7/9/python-and-pola/#seemingly-inverse-logic
źródło
module Enumerate
sekcji, ale Python nie działa w ten sposób, nie ma jednej nadklasy dla wszystkich iteratorów, w której można by umieścić tę metodę.Hash
iString
właściwie nie mam klasy kolekcji jako superklasy ... ich superklasa jest po prostuObject
. Więc te dwie klasy polegają tylko na mieszaniu Enumerable ... coś, co rozumiem, jak interfejs pozwalający na zestaw zachowań kolekcji