Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 子类'pathlib.Path'失败_Oop_Python 3.4 - Fatal编程技术网

Oop 子类'pathlib.Path'失败

Oop 子类'pathlib.Path'失败,oop,python-3.4,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") 这是我收到的错误信息 Traceback (most recent call last): File "/Us

我想增强类
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'
回溯(最近一次呼叫最后一次):
文件“/Users/projetmbc/test.py”,第14行,在
test=PPath(“dir”、“test.txt”)
文件“/anaconda/lib/python3.4/pathlib.py”,第907行,新__
self=cls.\u来自零件(args,init=False)
文件“/anaconda/lib/python3.4/pathlib.py”,第589行,在_from_parts中
drv,root,parts=self.\u parse\u args(args)
文件“/anaconda/lib/python3.4/pathlib.py”,第582行,在参数中
返回cls.\u flavor.parse\u部分(parts)
AttributeError:类型对象“PPath”没有属性“\u”
我做错了什么?

路径
类的定义。它做了一些相当聪明的事情。它不是直接从它的
\uuuuu new\uuuuu()
返回
路径的实例,而是返回子类的实例,但前提是它是作为
路径()
直接调用的(而不是作为子类)

否则,它将通过
WindowsPath()
PosixPath()
调用,这两种方法都通过多重继承提供了
\u
类属性。在子类化时,还必须提供此属性。为此,您可能需要实例化和/或子类化该类。API不支持这一部分,因此您的代码可能会在Python的未来版本中中断


TL;DR

下面是一个简单的方法,可以对Kevin的观察结果进行处理

class PPath():
    def __init__(self, *args, **kwargs):
        self.path = Path(*args, **kwargs)
然后我需要使用一个技巧,以便将所有路径的方法自动绑定到我的PPpath类。我认为这样做会很有趣。

注意 在对Python开发列表进行了一点讨论之后,我开始了本文

临时解决办法 很抱歉这个双重回答,但这里有一个方法来实现我想要的。感谢Kevin为我指出了
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 ? 
=== === === === 

您可以对具体实现进行子类化,这样可以:

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("я")
这也是工作

from pathlib import Path

class SystemConfigPath(type(Path())):
    def __new__(cls, **kwargs):
        path = cls._std_etc()
        return super().__new__(cls, path, **kwargs)

    @staticmethod
    def _std_etc():
        return '/etc'

name = SystemConfigPath()
name = name / 'apt'
print(name)
印刷品:

/etc/apt

@staticmethod可以被@classmethod取代,我也一直在努力解决这个问题

下面是我所做的,从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")

您可能能够简化您的生活,这取决于您想要扩展Path(或PosixPath,或WindowsPath)的原因。在我的例子中,我想实现一个文件类,该类包含所有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):
        ...

现在,如果file=file('/a/b/c'),我可以在file上使用整个路径接口,还可以执行file.foobar()。

结合前面的一些答案,您也可以编写:

类MyPath(pathlib.Path):
_味=类型(pathlib.Path())。\u味


对于传统的Python API来说,这是一个多么奇怪的选择。我想我必须照你的建议去做。这需要读取源代码。这不是问题,只是一点无聊的东西。@projetmbc:IMHO这是一个糟糕的设计;超类不应该显示其子类的知识,更不用说以这种方式依赖它们了<代码>路径()
应该是工厂函数。这可能值得一个bug报告,但由于这是一个主观意见的问题,我不确定bug追踪器是最好的开始。您可能会在Python或其他邮件列表上进行更有成效的对话,我想您和我都在Python开发人员邮件列表上发布了一条消息。另一方面,我的答案中的挑战是一件有趣的事情。我不会称之为聪明的自动绑定:尝试覆盖
\uuu getattr\uuu
。这不会捕获神奇的方法,因此您还需要覆盖
\uuuu div\uuuu
和(可能)覆盖
\uu rdiv\uuuu
以获得
foo/bar
语法。我的意思是说
\uuuu truediv\uuuu
或者
\uuu rtruediv\uuuu
。我已经更新了我的代码,以便自动使用de
div
语法。现在,我的主要问题是找到一种自动方法将
Path
的所有公共方法(如
is\u file
)绑定到我的类。再次,使用
\uu getattr\uuuu
将属性访问重定向到
Path
对象。这也会影响正常的方法。我会在下周尝试。如果我发现有用的东西,我会把它放在这里。我不确定这是个好主意。基本上,您将额外的方法直接附加到
WindowsPath
PosixPath
类,这意味着它将可用于这些类的所有实例,而不仅仅是通过
PathPlus
创建的实例。我想和您一样,但目前我使用的是这个不太完美的解决方案。为什么?如果我使用增强版的类路径,我不关心Windowsäth或PosixPath。事实上,在Python开发人员的邮件列表上,Guido自己说类路径的子类化必须比现在更容易实现。作为结论,我的解决方案是在路径变得更加pythonic之前进行临时修补。谢谢。这个方法很难看,但比我以前的方法要差得多。您可以按照下面的讨论进行操作。也许有一天他们会发布一个我们还没有遇到的解决方案。非常感谢!如果要使用
file=file(“a/b/c”)
进行实例化,那么在
\uuu init\uuuu
中不需要一个
self.path=pathlib.path(path)
,即
str
参数到
\uu init\uuu
path
参数吗?当然,self.path需要是一个pathlib.path。好的,你应该在回答中调整它(目前无法正常工作)好的,我修复了init。