ос.путь.вступать с ул. подкласс


Кто-нибудь знает, почему функция os.path.join не работает с подклассами str?

(я использую Python3. 2 x64 и Python2. 7 x86 на Windows, и результат тот же)

Это код, который у меня есть

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

p = Path(r'C:thepath')
d = p + 'some_file.txt'

И результат, который я хочу:

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

Но выход будет \some_file.txt независимо от значения self.

Я знаю, что могу сделать либо str(self), либо сохранить его как self.path и использовать позже, но почему os.join.path не принимает подкласс str и не вызывает ошибку (например, когда вы используете число или любой нестроковый тип)?

2 5

2 ответа:

Если вы сомневаетесь, проверьте источник (Python32\Lib\ntpath.py). соответствующие биты:

"""соедините два или более компонента pathname, вставляя" \ " по мере необходимости. Если какой-либо компонент является абсолютным путем, все предыдущие компоненты пути будут отброшены."" " (курсив добавлен)

В нижней части функции join пытается поместить \ между двумя частями с помощью path += '\\' + b (где b - это some_file.txt), который сначала добавляет \ и some_file.txt (которые являются простыми строками), затем добавляет Это к Path(r'c:\the\path'), вызывая Path.__add__(r'c:\the\path', r'\some_file.txt'), который будет снова вызывать os.path.join...

Вы обратили внимание на ведущую \ теперь на имени файла? Вот почему начальная часть пути теряется.

Вызов os.path.join с помощью str(self) (или self.path) работает, потому что тогда os.path.join вызывается только один раз, а не дважды.

Похоже, что os.path.join использует метод build in __add__, Это можно проверить, поместив оператор print в метод __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))

To

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

Это работает.