我想增强课程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'
我做错了什么?
答案 0 :(得分:14)
您可以对具体实现进行子类化,因此可以使用:
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("я")
答案 1 :(得分:7)
Here是Path
类的定义。它做的事情比较聪明。它不是直接从Path
返回__new__()
的实例,而是返回子类的实例,但只有 才会直接调用Path()
(和不作为子类)。
否则,它希望通过WindowsPath()
或PosixPath()
调用,它们都通过多重继承提供_flavour
类属性。您还必须在子类化时提供此属性。您可能需要实例化和/或子类化_Flavour
类才能执行此操作。这不是API支持的部分,因此您的代码可能会在未来的Python版本中中断。
答案 2 :(得分:3)
根据您为什么要扩展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):
...
现在,如果file = File('/ a / b / c'),我可以使用文件上的整个Path接口,也可以使用file.foobar()。
答案 3 :(得分:2)
在对Python dev进行一些讨论之后,我打开了a bug track here。列表。
很抱歉这个双重答案,但这是一种实现我想要的方法。感谢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 ?
=== === === ===
答案 4 :(得分:1)
我也一直在为此苦苦挣扎。
这是我在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")
答案 5 :(得分:0)
这是一个简单的方法来处理凯文的观察。
class PPath():
def __init__(self, *args, **kwargs):
self.path = Path(*args, **kwargs)
然后我将需要使用一个技巧,以便自动将所有Path的方法绑定到我的PPpath类。我认为这样做很有意思。
答案 6 :(得分:0)
也可以。
double (q[1])(X[2])={(double X[2]){return X[0]}};
打印:
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)
@staticmethod可以替换为@classmethod
答案 7 :(得分:0)
结合之前的一些答案,您也可以只写:
class MyPath(pathlib.Path):
_flavour = type(pathlib.Path())._flavour