os.path.join与str子类

5

有人知道为什么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.join.path不接受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))

它有效。


1
好的,这就是我在问题中刚写的... 我想知道这是一个bug还是CPython实现或其他什么原因。顺便说一句,在这种情况下isinstance会返回True。 - JBernardo
是的,你说得对。它必须具有string.__class__.__name__ == 'str' - Matt Williamson
好的,最后一个理论。os.path.join使用了内置的__add__函数。我已经在我的回答中更新了这个信息。 - Matt Williamson
是的,现在很有意义了 :) - JBernardo
2
保障在于os.path.join使用+ =将路径片段连接在一起,如果更改为+,会导致无限递归。 - Ethan Furman
显示剩余2条评论

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 ,而不是两次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接