python found Disimballare le generalizzazioni




python axes name (2)

Prendendo una citazione dal thread di mailing list di Py-Dev in cui questa funzione è stata accettata :

In modo che lascia le comprensioni. IIRC, durante lo sviluppo della patch ci siamo resi conto che f(*x for x in xs) è sufficientemente ambiguo da decidere di disabilitarlo - si noti che f(x for x in xs) è già un po 'un caso speciale perché l'argomento può essere solo un'espressione generatore "nuda" se è l'unico argomento. Lo stesso ragionamento non si applica (in questa forma) per elencare, impostare e dettare le comprensioni - mentre f(x for x in xs) è identico nel significato f((x for x in xs)) , [x for x in xs] NON è uguale a [(x for x in xs)] (questa è una lista di un elemento e l'elemento è un'espressione di generatore)

(Enfasi mia)

Ho anche dato un'occhiata al tracker di problemi di Python per questa funzione. Ho trovato un problema in cui la discussione ha avuto luogo durante l'implementazione. La sequenza di messaggi che li ha aiutati a giungere a questa realizzazione inizia here con una bella panoramica dell'ambiguità introdotta presentata in msg234766 da GvR.

Nel timore di link-rot, sto allegando il messaggio (formattato) qui:

Quindi penso che la funzione di test qui dovrebbe essere:

def f(*a, **k): print(list(a), list(k))

Quindi possiamo provare cose come:

f(x for x in ['ab', 'cd'])

che stampa un oggetto generatore, perché questo è interpretato come un argomento che è un'espressione generatore.

Ma ora consideriamo:

f(*x for x in ['ab', 'cd'])

Mi aspettavo che questo fosse equivalente a:

f(*'ab', *'cd')

IOW:

 f('a', 'b', 'c', 'd')

Il PEP non dà chiarezza su cosa fare qui. La domanda ora è, dovremmo interpretare cose come *x for x in ... come una forma estesa di espressione del generatore, o come una forma estesa di *arg ? In qualche modo penso che quest'ultimo sia più utile e anche l'estensione più logica.

Il mio ragionamento è che il PEP supporta cose come f(*a, *b) e sarebbe abbastanza logico interpretare f(*x for x in xs) come fare la cosa *x per ogni x nella lista xs .

Infine, come notato nella sezione Abstract del PEP corrispondente , questa funzione non è completamente esclusa:

Questo PEP non include gli operatori di disimballaggio all'interno di list, set e dizionari, anche se questo non è stato escluso per le proposte future .

Quindi, potremmo vederlo presto (sicuramente non 3,6, però :-) e spero che lo facciano, sono belli.

>>> LOL = [[1, 2], ['three']]
>>> [*LOL[0], *LOL[1]]
[1, 2, 'three']

Tutto apposto! Arrivederci itertools.chain . Non mi è mai piaciuto molto comunque.

>>> [*L for L in LOL]
  File "<ipython-input-21-e86d2c09c33f>", line 1
    [*L for L in LOL]
    ^
SyntaxError: iterable unpacking cannot be used in comprehension

Oh Perché non possiamo avere cose belle?

Disimballare in una comprensione sembra essere ovvio / pitonico, ma dal momento che si sono presi la briga di aggiungere quel messaggio di errore speciale c'era un motivo per disabilitarlo. Quindi, qual è il problema con quella sintassi?


Answer #1

Questo è brevemente spiegato nel PEP 448 che introduce le generalizzazioni di decompressione:

Le iterazioni precedenti di questo PEP consentivano agli operatori di disimballaggio all'interno di elenchi, insiemi e comprensibilità del dizionario come operatore di livellamento su iterables di contenitori:

>>> ranges = [range(i) for i in range(5)]
>>> [*item for item in ranges]
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3]

>>> {*item for item in ranges}
{0, 1, 2, 3}

Ciò è stato accolto da un misto di forti preoccupazioni in merito alla leggibilità e al supporto moderato. Per non svantaggiare gli aspetti meno controversi del PEP, questo non è stato accettato con il resto della proposta.

Tuttavia, questo potrebbe cambiare in futuro:

Questo PEP non include gli operatori di disimballaggio all'interno di list, set e dizionari, anche se questo non è stato escluso per le proposte future.





iterable-unpacking