2013-02-12 41 views
46

tôi có thể làmPython os.path.join() trên một danh sách

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

Tuy nhiên, khi tôi làm

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

tôi thiếu gì ở đây?

Trả lời

94

Vấn đề là, os.path.join không tham số list làm đối số, nó phải là đối số riêng biệt.

Đây là nơi *, các nhà điều hành 'splat' đến chơi ...

tôi có thể làm

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

một số ngữ cảnh khác cho splat: https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists –

+1

Lưu ý rằng tôi đã cố gắng sử dụng điều này để xóa phần cuối cùng của đường dẫn đầy đủ. Nó dẫn đến một [lỗi] (http: // stackoverflow.com/questions/31693272/errno-2-using-python-shutil-py-no-such-file-or-directory-cho-file-đích) (trong Mac), vì nó thiếu dấu gạch chéo đầu tiên tại '/ Users/... '. Để giải quyết nó, tôi đã thêm dấu gạch chéo hàng đầu theo cách thủ công, trong trường hợp ai đó phải đối mặt với cùng một vấn đề ... – J0ANMM

4

Nó chỉ là phương pháp. Bạn không thiếu gì cả. Các official documentation cho thấy rằng bạn có thể sử dụng danh sách giải nén để cung cấp nhiều con đường:

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

Lưu ý *s intead chỉ s trong os.path.join(*s). Sử dụng dấu hoa thị sẽ kích hoạt việc giải nén danh sách, có nghĩa là mỗi đối số danh sách sẽ được cung cấp cho hàm như một đối số riêng biệt.

+0

Nhìn tốt hơn vào liên kết của bạn một lần nữa ;-) –

+0

@ThorstenKranz Nghiêm túc? Liên kết hoàn toàn hoạt động. – Greg

+0

@Greg nó được ưu tiên trên SO để sao chép các phần liên quan vào câu trả lời chứ không phải chỉ dán một liên kết, do đó có thể là downvotes – SHernandez

14

Giả sử join không được thiết kế theo cách đó (mà nó là, như ATOzTOA chỉ ra), và nó chỉ mất hai tham số, bạn vẫn có thể sử dụng được xây dựng trong reduce:

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

Cùng đầu ra như :

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

Chỉ vì lý do đầy đủ và giáo dục (và cho các tình huống khác mà ở đó * không hoạt động).

Gợi ý cho Python 3 Đối với Python 3, reduce được chuyển sang mô-đun functools.

+1

Trong Python 3 'reduce' được chuyển sang mô-đun' functools' trong trường hợp bất kỳ ai khác đang tìm kiếm nó Tôi đã. –

+0

Cảm ơn bạn đã gợi ý, tôi sẽ điều chỉnh câu trả lời của tôi. –

+2

đáng tiếc rằng python đi nhiều hơn và nhiều hơn nữa từ phong cách chức năng thay vì ôm lấy nó và mở ra. việc di chuyển 'reduce' đến một mô-đun là một câu lệnh. – SHernandez

6

Tôi tình cờ gặp tình huống trong đó danh sách có thể trống. Trong trường hợp đó:

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

Lưu ý đối số đầu tiên sẽ không làm thay đổi kết quả.

0

Điều này cũng có thể được coi là thao tác giảm bản đồ đơn giản nếu bạn muốn nghĩ về nó từ góc độ lập trình chức năng.

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

reduce được xây dựng bằng Python 2.x. Trong Python 3.x nó đã được chuyển đến itertools Tuy nhiên, chấp nhận câu trả lời là tốt hơn.

Điều này đã được trả lời dưới đây nhưng trả lời nếu bạn có danh sách các mục cần được tham gia.

Các vấn đề liên quan