【问题标题】:os.path.join with str subclassos.path.join 与 str 子类
【发布时间】:2011-12-02 16:33:38
【问题描述】:

有人知道为什么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 子类也不引发错误(比如当你使用数字或任何非字符串类型)?

【问题讨论】:

    标签: python string path python-3.x


    【解决方案1】:

    如有疑问,请查看源代码 (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 只会被调用一次而不是两次。

    【讨论】:

      【解决方案2】:

      看起来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))
      

      有效。

      【讨论】:

      • 嗯,这就是我刚刚在我的问题中写的......我想知道它是一个错误还是 CPython 实现或其他什么。 BTW isinstance 在这种情况下将返回 True
      • 是的,你是对的。它必须有string.__class__.__name__ == 'str'
      • 不,解释器不会检查该字符串,因为我可以随时更改它...
      • 好的,最后一个理论。 os.path.join 使用内置的add。用该信息更新了我的答案
      • 保障措施是os.path.join 使用+= 将路径片段连接在一起——如果将其更改为+,则会发生无限递归。
      猜你喜欢
      • 1970-01-01
      • 2020-08-21
      • 2019-11-30
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      相关资源
      最近更新 更多