Подкласс `pathlib.Path` не работает
Я хотел бы улучшить класс pathlib.Path
, но простой пример выше дозы не работает.
from pathlib import Path
class PPath(Path):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
test = PPath("dir", "test.txt")
Вот сообщение об ошибке, которое у меня есть.
Traceback (most recent call last):
File "/Users/projetmbc/test.py", line 14, in <module>
test = PPath("dir", "test.txt")
File "/anaconda/lib/python3.4/pathlib.py", line 907, in __new__
self = cls._from_parts(args, init=False)
File "/anaconda/lib/python3.4/pathlib.py", line 589, in _from_parts
drv, root, parts = self._parse_args(args)
File "/anaconda/lib/python3.4/pathlib.py", line 582, in _parse_args
return cls._flavour.parse_parts(parts)
AttributeError: type object 'PPath' has no attribute '_flavour'
Что я делаю неправильно?
Ответы
Ответ 1
Вы можете подклассифицировать конкретную реализацию, поэтому это работает:
class Path(type(pathlib.Path())):
Вот что я сделал с этим:
import pathlib
class Path(type(pathlib.Path())):
def open(self, mode='r', buffering=-1, encoding=None, errors=None, newline=None):
if encoding is None and 'b' not in mode:
encoding = 'utf-8'
return super().open(mode, buffering, encoding, errors, newline)
Path('/tmp/a.txt').write_text("я")
Ответ 2
Здесь - это определение класса Path
. Он делает что-то довольно умное. Вместо прямого возврата экземпляра Path
из его __new__()
он возвращает экземпляр подкласса, но только если он был вызван непосредственно как Path()
(а не как подкласс).
В противном случае ожидается, что он будет вызван через WindowsPath()
или PosixPath()
, которые оба предоставляют атрибут класса _flavour
через множественное наследование. Вы также должны указать этот атрибут при подклассовке. Для этого вам, вероятно, потребуется создать экземпляр и/или подклассы класса _flavour
. Это не поддерживаемая часть API, поэтому ваш код может сломаться в будущей версии Python.
TL; DR: Эта идея чревата опасностью, и я боюсь, что мои ответы на ваши вопросы будут интерпретироваться как утверждение вместо неохотной помощи.
Ответ 3
Примечание
Я открыл здесь трек ошибок после небольшого обсуждения на Python dev. список.
Временное решение
Извините за этот двойной ответ, но вот способ добиться того, чего я хочу. Благодаря Кевину, который указывает мне на источник pathlib
и тот факт, что мы имеем здесь конструкторы.
import pathlib
import os
def _extramethod(cls, n):
print("=== "*n)
class PathPlus(pathlib.Path):
def __new__(cls, *args):
if cls is PathPlus:
cls = pathlib.WindowsPath if os.name == 'nt' else pathlib.PosixPath
setattr(cls, "extramethod", _extramethod)
return cls._from_parts(args)
test = PathPlus("C:", "Users", "projetmbc", "onefile.ext")
print("File ?", test.is_file())
print("Dir ?", test.is_dir())
print("New name:", test.with_name("new.name"))
print("Drive ?", test.drive)
test.extramethod(4)
Это печатает следующие строки.
File ? False
Dir ? False
New name: C:/Users/projetmbc/new.name
Drive ?
=== === === ===
Ответ 4
Вот простой способ сделать что-то относительно наблюдения Кевина.
class PPath():
def __init__(self, *args, **kwargs):
self.path = Path(*args, **kwargs)
Затем мне нужно будет использовать трюк, чтобы автоматически привязывать все методы Path к моему классу PPpath. Я думаю, что это будет забавно делать.