使用str子类的os.path.join

5 投票
2 回答
902 浏览
提问于 2025-04-17 03:50

有没有人知道为什么 os.path.join 这个函数在处理 str 的子类时不管用呢?

(我在 Windows 上用的是 Python3.2 x64 和 Python2.7 x86,结果都是一样的)

这是我写的代码:

class Path(str):
    def __add__(self, other):
        return Path(os.path.join(self, other))

p = Path(r'C:\the\path')
d = p + 'some_file.txt'

我想要的结果是:

'C:\\the\\path\\some_file.txt'

但是无论 self 的值是什么,输出的结果都是 \\some_file.txt

我知道我可以用 str(self) 转换一下,或者把它存成 self.path 以后再用,但为什么 os.path.join 不接受 str 的子类,也不报错(就像用数字或者其他非字符串类型时那样)呢?

2 个回答

1

看起来 os.path.join 这个函数使用了内置的 __add__ 方法。你可以通过在 __add__ 方法里加一个打印语句来验证这一点。

>>> class Path(str):
...     def __add__(self, other):
...             print 'add'
...             return Path(os.path.join(str(self), other))
... 
>>> p = Path(r'/the/path')
>>> p + 'thefile.txt'
add
>>> class Path(str):
...     def __add__(self, other):
...             print 'add'
...             return Path(os.path.join(self, other))
... 
>>> p = Path(r'/the/path')
>>> p + 'file.txt'
add
add
# add printed twice

最简单的解决办法是:

return Path(os.path.join(self, other))

把它改成:

return Path(os.path.join(str(self), other))

这样就可以用了。

0

如果有疑问,可以查看源代码(Python32\Lib\ntpath.py)。相关内容如下:

"""将两个或多个路径组件连接起来,必要时插入 "\"。如果任何组件是绝对路径,之前的所有路径组件都会被丢弃。"""(强调部分)

在函数 join 的底部,它试图在两个部分之间放一个 \,通过 path += '\\' + b 来实现(这里的 bsome_file.txt)——这首先添加了 \some_file.txt(这两个都是普通字符串),然后通过调用 Path.__add__(r'c:\the\path', r'\some_file.txt') 将它们添加到 Path(r'c:\the\path'),这又会 再次 调用 os.path.join...

你注意到文件名前面有一个 \ 吗?这就是为什么路径的前面部分会丢失的原因。

str(self)(或 self.path)调用 os.path.join 是有效的,因为这样 os.path.join 只会被调用一次,而不是两次。

撰写回答