2013-02-12 20 views
46

posso farePython os.path.join() su una lista

>>> os.path.join("c:/","home","foo","bar","some.txt") 
'c:/home\\foo\\bar\\some.txt' 

Ma, quando lo faccio

>>> s = "c:/,home,foo,bar,some.txt".split(",") 
>>> os.path.join(s) 
['c:/', 'home', 'foo', 'bar', 'some.txt'] 

Che cosa mi manca qui?

risposta

94

Il problema è, os.path.join non accetta un argomento come list, deve essere separato.

Questo è dove *, l'operatore 'splat' entra in gioco ...

posso fare

>>> s = "c:/,home,foo,bar,some.txt".split(",") 
>>> os.path.join(*s) 
'c:/home\\foo\\bar\\some.txt' 
+7

un po 'più di contesto per splat: https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists –

+1

Nota che ho provato a usare questo per rimuovere l'ultima parte di un percorso completo. Ha provocato un [errore] (http: // StackOverflow.it/questions/31693272/errno-2-using-python-shutil-py-no-tale-file-o-directory-per-destinazione-file) (in Mac), poiché mancava la prima barra a '/ Users/... '. Per risolvere il problema, ho aggiunto quella barra in modo manuale, nel caso qualcuno affrontasse lo stesso problema ... – J0ANMM

4

E 'solo il metodo. Non ti manca nulla. Il official documentation mostra che è possibile utilizzare l'elenco disimballaggio per la fornitura di diversi percorsi:

s = "c:/,home,foo,bar,some.txt".split(",") 
os.path.join(*s) 

Annotare il *s intead di appena s in os.path.join(*s). L'uso dell'asterisco attiverà lo spacchettamento della lista, il che significa che ciascun argomento di lista verrà fornito alla funzione come argomento separato.

+0

Meglio guardare ancora una volta il tuo link ;-) –

+0

@ThorstenKranz Seriamente? Il collegamento funziona completamente. – Greg

+0

@Greg è preferibile su SO copiare le parti rilevanti nella risposta e non semplicemente incollare un collegamento, forse quindi i downvotes – SHernandez

14

Supponendo join non è stato progettato in questo modo (che è, come ha sottolineato ATOzTOA), e ci sono voluti solo due parametri, si potrebbe ancora utilizzare il built-in reduce:

>>> reduce(os.path.join,["c:/","home","foo","bar","some.txt"]) 
'c:/home\\foo\\bar\\some.txt' 

stessa uscita come :

>>> os.path.join(*["c:/","home","foo","bar","some.txt"]) 
'c:/home\\foo\\bar\\some.txt' 

Solo per completezza e ragioni didattiche (e per altre situazioni in cui * non funziona).

suggerimento per Python 3 Per Python 3, reduce stato spostato al modulo functools.

+1

In Python 3 'reduce' è stato spostato nel modulo' functools' nel caso in cui qualcun altro lo cercasse come Ero. –

+0

Grazie per il suggerimento, aggiusterò la mia risposta. –

+2

peccato che il pitone si allontani sempre più dallo stile funzionale invece di abbracciarlo e aprirsi. spostare 'reduce' su un modulo è una dichiarazione. – SHernandez

6

Mi sono imbattuto nella situazione in cui l'elenco potrebbe essere vuoto. In tal caso:

os.path.join('', *the_list_with_path_components) 

Nota il primo argomento, che non modifica il risultato.

0

Questo può essere anche pensato come una semplice mappa che riduce l'operazione se si desidera pensarlo da una prospettiva di programmazione funzionale.

import os 
folders = [("home",".vim"),("home","zathura")] 
[reduce(lambda x,y: os.path.join(x,y), each, "") for each in folders] 

reduce è BUILTIN in Python 2.x. In Python 3.x è stato spostato su itertools Tuttavia la risposta accettata è migliore.

Questa è stata una risposta sotto, ma rispondendo se si dispone di un elenco di elementi che devono essere uniti.