web-dev-qa-db-ja.com

Pythonリストのos.path.join()

できます

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

しかし、私がするとき

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

ここで何が欠けていますか?

73
ATOzTOA

問題は、os.path.joinlistを引数として受け取らないことです。別の引数である必要があります。

これは、*、 'splat'演算子が作用する場所です...

できます

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

joinはそのように設計されておらず(ATOzTOAが指摘したように)、2つのパラメーターしか必要としないと仮定すると、組み込みのreduceを使用できます。

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

次のような同じ出力:

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

完全性と教育上の理由のために(および*が機能しない他の状況のた​​めに)。

Python 3のヒント Python 3の場合、reducefunctoolsモジュールに移動されました。

19
Thorsten Kranz

リストが空かもしれない状況につまずいた。その場合:

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

結果を変更しない最初の引数に注意してください。

8
Sebastian Mach

ただの方法です。あなたは何も見逃していません。 公式ドキュメント は、リストの展開を使用して複数のパスを提供できることを示しています。

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

os.path.join(*s)内のsだけの*sに注意してください。アスタリスクを使用すると、リストのアンパックがトリガーされます。つまり、各リストの引数は個別の引数として関数に提供されます。

6
Greg

関数型プログラミングの観点から考えたい場合、これは単純なmap reduce操作と考えることもできます。

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

reduceはPython 2.xに組み込まれています。 Python 3.xでは、itertoolsに移動しましたが、受け入れられた答えの方が優れています。

これは以下で回答されていますが、参加する必要があるアイテムのリストがある場合は回答しています。

0
Nishant