pathlib的简单子类化出错。路径:无属性

2024-04-23 06:54:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从pathlib中创建子类Path,但在实例化时由于以下错误而失败

from pathlib import Path
class Pl(Path):
    def __init__(self, *pathsegments: str):
        super().__init__(*pathsegments)

实例化时出错

AttributeError: type object 'Pl' has no attribute '_flavour'

更新: 我继承的WindowsPath仍然不起作用

TypeError: object.__init__() takes exactly one argument (the instance to initialize)


Tags: path实例fromimportselfobjectinitdef
3条回答

我解决了。Mokey补丁是一条路要走

像这样定义函数

def method1(self, other):
   blah

Path.method1 = method1

最快、最简单、最方便的解决方案,零缺点。Pycharm中的Autosuggest运行良好

更新:

我得到了解决方案(与linter和auto Suggester一起使用):

class MyPath(type(Path()), Path):
    pass

Path是一个抽象类,实际上根据操作系统实例化为两个可能的子类:

PosixPathWindowsPath

https://docs.python.org/3/library/pathlib.html

这个基类寻找一个内部(私有)类变量来确定它实际上是什么类型的对象,这个变量称为_flavour

你有两个选择:

  1. 从一个具体的子类派生类。
    这是最好的选择,因为它将避免您处理未记录的库内部,并保证您的代码不会在库的不同版本上中断。
    如果希望代码跨平台,则需要根据操作系统对类进行不同的定义

代码如下所示:

import os

if os.name == 'posix':
    base = PosixPath
else:
    base = WindowsPath

class P1(base):
    def __init__(self, *pathsegments: str):
        super().__init__(*pathsegments)
  1. 或者自己填写类变量。
    不建议这样做,因为您将使用未记录的元素,这些元素可能会随着库的任何更改而随时中断,但它将允许您直接从Path继承

注意,如果您决定使用此方法,可能会出现其他问题

import os
from pathlib import _PosixFlavour
from pathlib import _WindowsFlavour

class P1(Path):
    _flavour = _PosixFlavour() if os.name == 'posix' else _WindowsFlavour()

    def __init__(self, *pathsegments: str):
        super().__init__(*pathsegments)

部分问题在于Path类在__new__中实现了一些条件逻辑,这些逻辑实际上不适合子类化。具体而言:

    def __new__(cls, *args, **kwargs):
        if cls is Path:
            cls = WindowsPath if os.name == 'nt' else PosixPath

这会将从Path(...)返回的对象类型设置为PosixPathWindowsPath,但仅设置为if cls is Path,这对于Path的子类来说永远不会为真

这意味着在__new__函数中,cls won't have the{{}*WindowsPath和*PosixPath类),因为Pl类没有_flavour属性

我认为您最好显式地将其他类中的一个子类化,例如PosixPathWindowsPath

相关问题 更多 >