为什么 Python pathlib relative_to 允许多个输入路径?
Why does Python pathlib relative_to allow multiple input paths?
这里为什么用*other
。传入多个路径是什么意思?
PurePath.relative_to(*other)
https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.relative_to
好像只有最后一个重要
In [1]: p = Path('/etc/pass')
[PYFLYBY] from pathlib import Path
In [2]: p.relative_to('arsta', '/etc', '/etc')
Out[2]: PosixPath('pass')
In [3]: p.relative_to('arsta', '/etc', '/etc/')
Out[3]: PosixPath('pass')
In [4]: p.relative_to('arsta', '/etc', '/etc/arstar')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-1669e7092659> in <module>
----> 1 p.relative_to('arsta', '/etc', '/etc/arstar')
/opt/schrodinger/suites2022-1/internal/lib/python3.8/pathlib.py in relative_to(self, *other)
906 if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
907 formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
--> 908 raise ValueError("{!r} does not start with {!r}"
909 .format(str(self), str(formatted)))
910 return self._from_parsed_parts('', root if n == 1 else '',
ValueError: '/etc/pass' does not start with '/etc/arstar'
其他测试用例
In [8]: p.relative_to('/etc', 'pass')
Out[8]: PosixPath('.')
In [9]: p.relative_to('axx', '/etc', 'pass')
Out[9]: PosixPath('.')
In [10]: p.relative_to('/axx', '/etc', 'pass')
Out[10]: PosixPath('.')
也许预期的用途是 ['/etc', 'pass']
?如何在这个有效列表形式和 /etc/pass
之间来回转换?
relative_to
的参数被连接起来以形成一个完整的路径(如果它们是相对的)。也就是这个:
>>> path = Path('/usr/bin/mkdir')
>>> path.relative_to('/usr/bin')
PosixPath('mkdir')
等同于:
>>> path = Path('/usr/bin/mkdir')
>>> p.relative_to('/usr', 'bin')
PosixPath('mkdir')
如果其中一个参数是绝对路径,则会屏蔽任何前面的路径:
>>> path = Path('/usr/bin/mkdir')
>>> path.relative_to('/usr', 'bin', '/etc')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.10/pathlib.py", line 816, in relative_to
raise ValueError("{!r} is not in the subpath of {!r}"
ValueError: '/usr/bin/mkdir' is not in the subpath of '/etc' OR one path is relative and the other is absolute.
是的,目的是允许从单独的部分指定路径,而无需使用 (platform-dependent) 路径分隔符。
从测试套件中可以清楚地看出这一点 (src):
def test_relative_to_common(self):
P = self.cls
p = P('a/b')
...
self.assertEqual(p.relative_to('a/b'), P())
# With several args.
self.assertEqual(p.relative_to('a', 'b'), P())
并且它也类似于 pathlib 中接受 *args
的其他接口,例如:
>>> Path("/usr").joinpath("local", "bin")
PosixPath('/usr/local/bin')
>>> Path(".").joinpath("a", "b", "c")
PosixPath('a/b/c')
>>> Path(Path.home(), "music", "mp3s")
PosixPath('/home/wim/music/mp3s')
这里为什么用*other
。传入多个路径是什么意思?
PurePath.relative_to(*other)
https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.relative_to
好像只有最后一个重要
In [1]: p = Path('/etc/pass')
[PYFLYBY] from pathlib import Path
In [2]: p.relative_to('arsta', '/etc', '/etc')
Out[2]: PosixPath('pass')
In [3]: p.relative_to('arsta', '/etc', '/etc/')
Out[3]: PosixPath('pass')
In [4]: p.relative_to('arsta', '/etc', '/etc/arstar')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-1669e7092659> in <module>
----> 1 p.relative_to('arsta', '/etc', '/etc/arstar')
/opt/schrodinger/suites2022-1/internal/lib/python3.8/pathlib.py in relative_to(self, *other)
906 if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts):
907 formatted = self._format_parsed_parts(to_drv, to_root, to_parts)
--> 908 raise ValueError("{!r} does not start with {!r}"
909 .format(str(self), str(formatted)))
910 return self._from_parsed_parts('', root if n == 1 else '',
ValueError: '/etc/pass' does not start with '/etc/arstar'
其他测试用例
In [8]: p.relative_to('/etc', 'pass')
Out[8]: PosixPath('.')
In [9]: p.relative_to('axx', '/etc', 'pass')
Out[9]: PosixPath('.')
In [10]: p.relative_to('/axx', '/etc', 'pass')
Out[10]: PosixPath('.')
也许预期的用途是 ['/etc', 'pass']
?如何在这个有效列表形式和 /etc/pass
之间来回转换?
relative_to
的参数被连接起来以形成一个完整的路径(如果它们是相对的)。也就是这个:
>>> path = Path('/usr/bin/mkdir')
>>> path.relative_to('/usr/bin')
PosixPath('mkdir')
等同于:
>>> path = Path('/usr/bin/mkdir')
>>> p.relative_to('/usr', 'bin')
PosixPath('mkdir')
如果其中一个参数是绝对路径,则会屏蔽任何前面的路径:
>>> path = Path('/usr/bin/mkdir')
>>> path.relative_to('/usr', 'bin', '/etc')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.10/pathlib.py", line 816, in relative_to
raise ValueError("{!r} is not in the subpath of {!r}"
ValueError: '/usr/bin/mkdir' is not in the subpath of '/etc' OR one path is relative and the other is absolute.
是的,目的是允许从单独的部分指定路径,而无需使用 (platform-dependent) 路径分隔符。
从测试套件中可以清楚地看出这一点 (src):
def test_relative_to_common(self):
P = self.cls
p = P('a/b')
...
self.assertEqual(p.relative_to('a/b'), P())
# With several args.
self.assertEqual(p.relative_to('a', 'b'), P())
并且它也类似于 pathlib 中接受 *args
的其他接口,例如:
>>> Path("/usr").joinpath("local", "bin")
PosixPath('/usr/local/bin')
>>> Path(".").joinpath("a", "b", "c")
PosixPath('a/b/c')
>>> Path(Path.home(), "music", "mp3s")
PosixPath('/home/wim/music/mp3s')