Python:获取路径中所有父级的可迭代的优雅方法

问题描述 投票:0回答:3

使用基于路径的资源系统,应用程序需要找到第一个基于路径管理给定资源的工作资源。我需要一种简洁的 Python 方式来生成以下内容:

输入:

/house/dogs/ralph/bone

输出:

/house/dogs/ralph/bone
/house/dogs/ralph
/house/dogs
/house

注意:可以使用

os.path
或类似的内置函数,但这些不是文件系统资源。输出可以是任何可迭代的(列表、集合、生成器等)。

python iterable
3个回答
7
投票

使用

pathlib
PurePath
为与文件系统没有关系的类似路径的对象提供了一个抽象接口。特别的,
PurePosixPath
是使用正斜杠(
/
)作为分隔符的那种:

>>> from pathlib import PurePosixPath
>>> p = PurePosixPath('/house/dogs/ralph/bone')
>>> str(p.parent)
/house/dogs/ralph
>>> str(p.parent.parent)
/house/dogs

您可以轻松循环播放:

p = PurePosixPath(...)
while str(p) != p.root:
    # Do stuff to p
    p = p.parent

一个相当Python式的最后修饰就是让它成为一个生成器:

def receding_path(p):
    p = PurePosixPath(p)
    while str(p) != p.root:
        yield str(p)
        p = p.parent

for item in receding_path('/house/dogs/ralph/bone'):
    # do stuff to each item

2
投票

前两个答案的组合:

import pathlib
import os
def resources(path):
  parts = pathlib.Path(path).parts
  for n in range(len(parts), 1, -1):
    yield os.path.join(*parts[:n])

1
投票

一种方法是在

"/"
上分割字符串并获取连续的切片。

in_string = "/house/dogs/ralph/bone"
s = in_string.split("/")
out_strings = list(filter(None, ("/".join(s[:i+1]) for i in range(len(s)))))
print(out_strings)
#['/house', '/house/dogs', '/house/dogs/ralph', '/house/dogs/ralph/bone']

filter(None, ...)
用于删除空字符串。

或者如果您希望按照您在帖子中指定的顺序输出,请反转范围:

out_strings = list(filter(None, ("/".join(s[:i]) for i in range(len(s), 0, -1))))
print(out_strings)
#['/house/dogs/ralph/bone',
# '/house/dogs/ralph',
# '/house/dogs',
# '/house']
© www.soinside.com 2019 - 2024. All rights reserved.