Python:获取路径中所有父对象的可迭代对象的优雅方式
Python: Elegent way to get an iterable of all parents in a path
使用基于路径的资源系统,应用程序需要找到第一个基于路径管理给定资源的工作资源。我需要一种简洁的 pythonic 方式来生成以下内容:
输入:
/house/dogs/ralph/bone
输出:
/house/dogs/ralph/bone
/house/dogs/ralph
/house/dogs
/house
注意:可以使用 os.path
或类似的内置插件,但这些不是文件系统资源。输出可以是任何可迭代的(列表、集合、生成器等)。
使用pathlib
. PurePath
s offer an abstract interface to path-like objects that have no relationship to the file system. In particular, 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 p != p.root:
# Do stuff to p
p = p.parent
一个相当 pythonic 的画龙点睛之笔是让它成为一个生成器:
def receding_path(p):
p = PurePosixPath(p)
while p != p.root:
yield str(p)
p = p.parent
for item in receding_path('/house/dogs/ralph/bone'):
# do stuff to each item
一种方法是在 "/"
上拆分字符串并连续切片。
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, ...)
用于删除空字符串。
如果您想要按照您在 post 中指定的顺序输出,或者反转范围:
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']
前两个答案的组合:
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])
使用基于路径的资源系统,应用程序需要找到第一个基于路径管理给定资源的工作资源。我需要一种简洁的 pythonic 方式来生成以下内容:
输入:
/house/dogs/ralph/bone
输出:
/house/dogs/ralph/bone
/house/dogs/ralph
/house/dogs
/house
注意:可以使用 os.path
或类似的内置插件,但这些不是文件系统资源。输出可以是任何可迭代的(列表、集合、生成器等)。
使用pathlib
. PurePath
s offer an abstract interface to path-like objects that have no relationship to the file system. In particular, 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 p != p.root:
# Do stuff to p
p = p.parent
一个相当 pythonic 的画龙点睛之笔是让它成为一个生成器:
def receding_path(p):
p = PurePosixPath(p)
while p != p.root:
yield str(p)
p = p.parent
for item in receding_path('/house/dogs/ralph/bone'):
# do stuff to each item
一种方法是在 "/"
上拆分字符串并连续切片。
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, ...)
用于删除空字符串。
如果您想要按照您在 post 中指定的顺序输出,或者反转范围:
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']
前两个答案的组合:
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])