子类`pathlib.Path`失败

pro*_*mbc 19 oop python-3.4

我想提升课程,pathlib.Path但上面的简单例子不起作用.

from pathlib import Path

class PPath(Path):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

test = PPath("dir", "test.txt")
Run Code Online (Sandbox Code Playgroud)

这是我的错误消息.

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'
Run Code Online (Sandbox Code Playgroud)

我做错了什么?

Ole*_*pin 15

您可以子类化具体实现,因此这有效:

class Path(type(pathlib.Path())):
Run Code Online (Sandbox Code Playgroud)

这是我对此所做的:

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("?")
Run Code Online (Sandbox Code Playgroud)


Nig*_*ain 10

结合之前的一些答案,您也可以这样写:

class MyPath(pathlib.Path):
    _flavour = type(pathlib.Path())._flavour
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 7

Path该类的定义.它做的事情比较聪明.它不是直接Path__new__()它返回一个实例,而是返回一个子类的实例,但只有当它被直接调用为Path()(而不是作为子类)时才会返回.

否则,它期望已通过任一被调用WindowsPath()PosixPath(),这两者都提供一个_flavour经由多重继承类属性.您还必须在子类化时提供此属性.您可能需要实例化和/或子_Flavour类化该类才能执行此操作.这不是API支持的部分,因此您的代码可能会在未来的Python版本中中断.

TL; DR:这个想法充满了危险,我担心我对你问题的回答将被解释为批准而不是不情愿的帮助.

  • @projetmbc:恕我直言,这是糟糕的设计;超类不应该显示其子类的知识,更不用说以这种方式*依赖它们*。`Path()` 应该是一个工厂函数。可能值得提交错误报告,但由于这是主观意见的问题,我不确定错误跟踪器是否是最好的起点。您可能会在 [Python-Dev](https://mail.python.org/mailman/listinfo/python-dev) 或其他邮件列表上进行更高效的对话。 (2认同)
  • 我不会称之为聪明 (2认同)

小智 6

我也一直在为此苦苦挣扎。

这就是我所做的,从 pathlib 模块学习。在我看来,这是更干净的方法,但如果 pathlib 模块更改其实现,它可能不会成立。

from pathlib import Path
import os
import pathlib

class PPath(Path):

    _flavour = pathlib._windows_flavour if os.name == 'nt' else pathlib._posix_flavour

    def __new__(cls, *args):
        return super(PPath, cls).__new__(cls, *args)

    def __init__(self, *args):
        super().__init__() #Path.__init__ does not take any arg (all is done in new)
        self._some_instance_ppath_value = self.exists() #Path method

    def some_ppath_method(self, *args):
        pass

test = PPath("dir", "test.txt")
Run Code Online (Sandbox Code Playgroud)


Jac*_*ein 5

根据您想要扩展 Path(或 PosixPath 或 WindowsPath)的原因,您或许能够简化您的生活。就我而言,我想实现一个 File 类,该类具有 Path 的所有方法以及其他一些方法。但是,我实际上并不关心 isinstance(File(), Path)。

委托工作得很好:

class File:

    def __init__(self, path):
        self.path = pathlib.Path(path)
        ...

    def __getattr__(self, attr):
        return getattr(self.path, attr)

    def foobar(self):
        ...
Run Code Online (Sandbox Code Playgroud)

现在,如果 file = File('/a/b/c'),我可以在文件上使用整个 Path 接口,也可以执行 file.foobar()。