我的具体用例是我试图继承pathlib.Path
。我希望能够添加或覆盖某些功能,但我还想继承所有Path。路径有__new__
,其中包含:
if cls is Path:
cls = WindowsPath if os.name == 'nt' else PosixPath
换句话说,Path需要将适当的类传递给它。问题是我不知道如何创建MY课程并使用Path.__new__
致电cls == Path
。
我尝试了很多东西,每个人都给了我一个不同的问题。
这个给了我AttributeError: type object 'RPath' has no attribute '_flavour'
,因为我试图覆盖父类。
Python3:
class RPath(Path):
def __new__(cls, basedir, *args, **kwargs):
return Path.__new__(cls, *args, **kwargs)
def __init__(self, basedir, *pathsegs):
super().__init__()
self.basedir = basedir
def newfunction(self):
print('Something new')
这个返回一个Path对象,因此不允许我进行覆盖。
def __new__(cls, basedir, *args, **kwargs):
return Path.__new__(Path, *args, **kwargs)
我也尝试了super()
的各种用法,但没有用。
这似乎应该很容易。我错过了什么?
更新:我想要完成什么?
具体来说,我想制作class RPath(basedir, *pathsegments)
:
rpath=RPath('\root\dir', 'relpath\path2\file.ext)
assert rpath.basedir == '\root\dir' # True
rpath.rebase('\new_basedir')
assert rpath.basedir === '\newbasedir' # True
# And while I'm at it
assert rpath.str == str(rpath) # make str a property == __str__(self)
答案 0 :(得分:2)
我不认为这会以通常的方式实现。但即使你能做到这一点,它也行不通,因为Path正在做的事情也不是返回一个普通的Path,而是返回一些子类(WindowsPath或PosixPath)。所以你对Path的覆盖不会生效,因为如果你能够继承Path.__new__
,它仍然会返回一个WindowsPath,而WindowsPath继承自Path,而不是你的自定义路径子类。
似乎pathlib.Path
有一个特殊的类结构,你必须做一些特殊的工作来复制它。首先,您需要创建自己的WindowsPath和PosixPath子类,然后创建一个Path子类,该子类委托实例化其中一个而不是自身。
答案 1 :(得分:1)
这是 a 解决方案,但它不使用继承。我仍然怀疑有一种直接的,简单的继承方式(虽然看到BrenBarn对另一方的回应)。
此方法使用合成。关键是使用__getattr__
和getattr()
自动将包装类中未找到的所有请求委托给包装类。这是一个例子:
class RPath(object):
def __init__(self, basedir, *pathsegs):
self.p = Path(*pathsegs)
self.basedir = basedir
# Override existing behavior
def __eq__(self, other):
return type(other) is RPath and self.basedir == other.basedir and self.p == other.p
# Add new behavior
def cp(self):
return self.basedir / self.p
# Everything not found here, automatically delegate to Path
def __getattr__(self, attr):
return getattr(self.cp, attr)
答案 2 :(得分:0)