Perché le funzioni di programmazione della funzione python non sono metodi di raccolta? [duplicare]

1

In altre parole, c'è un motivo correlato al design Python per esserlo?

Funzioni come map, filter, reduce ecc. sono semplici funzioni.

È solo una scelta di design scadente (se è buona, per favore spiega)? Ad esempio in scala, puoi concatenare metodi di raccolta come smth.map(func1).reduce(func2) . Mi sembra molto più conveniente.

    
posta Ivan 23.04.2015 - 16:37
fonte

3 risposte

1

In quale classe metteresti questi metodi?

In python, posso usare map su liste, tuple, dizionari, file, stringhe, insiemi, matrici, ecc. Non esiste una classe base di raccolta per mettere un map , reduce , filter ecc. on.

Ora, python avrebbe potuto avere una classe di raccolta da cui ereditavano tutte queste diverse cose. Ma sarebbe davvero contro lo "spirito" di Python. In python tutto è anatra battuto a macchina. Le cose funzionano in virtù del fatto che hai i giusti metodi. Puoi utilizzare map , reduce e filter su tutto ciò che definisce __iter__ . Dovendo sottoclasse una classe di raccolta andrebbe contro quella.

Così com'è, map / reduce / filter non sono realmente considerate le soluzioni pythonic.

Invece di map(x, lambda y: y+1) usa [y + 1 for y in x]

Invece di filter(x, lambda y: y % 2 == 0) usa [y for y in x if y % 2 == 0]

Invece di reduce(x, lambda x,y: x+y) usa

sum = 0
for y in x:
   sum += y
    
risposta data 23.04.2015 - 17:27
fonte
0

Penso che questo sia solo un artefatto storico. Queste funzioni sono state introdotte un po 'di tempo fa, quando le interfacce fluide non erano di gran moda. Da allora tutti si sono abituati a loro. (Quindi sì, puoi scriverlo come "cattivo design").

Queste funzioni potrebbero essere adattate alle liste? Forse, ma non era e non avrebbe dovuto essere fatto.

Primo, There should be one-- and preferably only one --obvious way to do it.

In secondo luogo, e soprattutto, map , reduce e molte altre funzioni funzionano non solo con le liste ma con qualsiasi che è iterabile. Lavorano su tuple, set, dicts e, soprattutto, su tutte le classi definite dall'utente che implementano l'iterazione (tramite __iter__ ) o generatori (tramite yield ).

Quindi, ogni iterabile o generatore dovrebbe in qualche modo ricevere le proprie implementazioni di map , reduce e probabilmente un sacco di altre funzioni che accettano un generatore iterabile e restituiscono qualcosa di compatibile. Ciò richiederebbe che qualsiasi classe esistente che sia iterabile non esponga nomi come map e reduce . Le modifiche al codice sono molto disapprovate dai manutentori e dalla comunità di Python.

Invece, puoi avvolgere le cose nella tua classe che offre l'interfaccia aggiuntiva e goderti lo stile fluido che hai menzionato, oppure stile pipe , o qualsiasi altra cosa.

    
risposta data 23.04.2015 - 17:14
fonte
0

Alcune considerazioni sulla seconda parte della domanda:

Is it just a poor design choice (if it is a good one, please explain)? For example in scala, you can chain collection methods like smth.map(func1).reduce(func2). It seems much more convenient to me.

Non penso che sia un design scadente: Python supporta sia gli stili procedurali che quelli orientati agli oggetti, e uno dei due stili doveva essere scelto per le funzioni di ordine superiore nelle raccolte. Ruby e Scala preferiscono lo stile orientato agli oggetti e quindi scelgono metodi di ordine elevato.

Per quanto riguarda la praticità del concatenamento dei metodi, hai una sintassi compatta corrispondente nelle lingue che supportano il curriculum, ad es. in Haskell puoi scrivere

(map func1 . filter func2) smthg

Probabilmente puoi fare qualcosa di simile in Python (vedi ad esempio PyMonad ) anche se non sarebbero le funzioni standard .

    
risposta data 23.04.2015 - 19:33
fonte