L'unione di Python sembra concentrarsi non sugli elementi da unire, ma sul simbolo, rispetto a Ruby o Smalltalk, per un motivo di progettazione?


9

Pensavo che una delle pietre miliari di OOP fosse che abbiamo oggetti, che sono gli oggetti con cui siamo interessati a trattare, e quindi inviamo loro dei messaggi.

Quindi può sembrare naturale che io abbia una collezione di oggetti e ho bisogno di metterli in una stringa, quindi per farlo:

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

(Smalltalk fa allo stesso modo). Si " | "è in qualche modo pensato come un argomento, un segno di come unirsi a esso. Può " "anche essere , se il tabellone deve essere più semplice. Quindi l'elemento di unione " | "non è particolarmente qualcosa che ci interessa - non sono gli oggetti principali del programma che hanno particolare importanza o significato.

Se Python lo fa usando

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

È un po 'strano che sembra quasi di passare un messaggio all'argomento, per dire l'argomento su qualcosa. Forse Python è più procedurale? Dire alla stringa di giunzione di svolgere un certo compito per noi?

È per salvare l'implementazione, in modo che non dobbiamo definire un joinper ogni classe di raccolta che abbiamo? Ma non è vero che possiamo anche scrivere una sola volta per qualsiasi classe di raccolta, come in Ruby:

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

(qualcosa del genere, invocando to_sogni elemento, facendo affidamento su to_sciascuna classe per fare la propria cosa, convertirsi in una stringa e poi concatenarli). Quindi non dobbiamo implementare per ciascuna stringa, hash o set, o qualunque classe di raccolta abbiamo.

O Python fuori non va sulla rotta OOP? Utilizza len("abc")e type([])invece "abc".len()o [].type()anche in Python3 sembra. Python lo fa in questo modo per motivi di design?


7
Da The Zen of Python : "Dovrebbe esserci uno - e preferibilmente solo un - modo oscuro di farlo. Anche se in quel modo all'inizio potrebbe non essere ovvio a meno che tu non sia olandese."
kdgregory,

2
In una forma, la raccolta sa come convertirsi in una stringa con un delimitatore, nell'altra una stringa sa come concatenare una raccolta usando se stessa come delimitatore. Sono entrambi orientati agli oggetti, ma cambiano soggetto e oggetto del verbo.
kdgregory,

Maybe Python is more procedural?Python era un linguaggio procedurale con alcune aggiunte funzionali ("Python ha acquisito lambda, reduce (), filter () e map (), per gentile concessione di un hacker Lisp che li ha persi e ha inviato patch funzionanti") fino a quello che sembra essere da qualche parte nella versione 2. È stato circa un decennio e mezzo dopo che è stato lavorato per la prima volta.

1
E anche oggi Python non sta nemmeno cercando di essere un linguaggio OOP, è completamente multi-paradigma.

Come C ++, Python è un linguaggio che consente OOP. Questo non è lo stesso di un linguaggio OOP come Java o Smalltalk.
Gort il robot il

Risposte:


9

Il join di Python è progettato per funzionare su qualsiasi iterabile . Ciò significa che i progettisti hanno dovuto decidere dove metterlo. Dato che funziona su più di un semplice elenco, ma richiede sempre (separatore) e restituisce una stringa, hanno deciso di renderlo parte del tipo di stringa.

Armin Ronacher lo dice meglio di me:

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

"Immagina che Python non funzioni in questo modo. Dovresti prima convertire l'iterabile in un vero elenco per convertirlo in una stringa. Le persone di Ruby ora sostengono che Ruby risolve questo problema mescolando i moduli, e sicuramente hanno ragione che questo è un'opzione, ma questa è una decisione di progettazione consapevole nel linguaggio che ha molte implicazioni. Python incoraggia l'accoppiamento libero avendo questi protocolli in cui le implementazioni reali possono essere altrove. Un oggetto è iterabile, un'altra parte del sistema sa come realizzarlo in una stringa ".


1
OP tenta di risolvere questo problema con la module Enumeratesezione ma Python non funziona in questo modo, non esiste una singola superclasse per tutti gli iteratori in cui è possibile inserire questo metodo.

Ho provato anche in Ruby 2.0 ... Hashe in Stringrealtà non ho una classe di raccolta come superclasse ... la loro superclasse è giusta Object. Quindi queste due classi fanno affidamento solo sull'enumerabile mixin ... qualcosa che ho capito come un'interfaccia per consentire l'insieme di comportamenti di una collezione
polarità,

Quindi è praticamente una limitazione del fatto che "iterabile" non è una classe o qualcosa con un codice reale, ma piuttosto un modello di digitazione anatra? In alternativa, è semplicemente perché Python voleva essere così generale da poter lavorare su qualsiasi raccolta con la stessa implementazione (mentre molte altre librerie standard la implementerebbero per ogni raccolta se effettivamente si applica a quella raccolta).
Kat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.