如何覆盖 python 中的 getattr 或 getattribute 以在惰性递归目录列表中调用其内部的 getattr 或 getattribute
How to override getattr or getattribute in python to call gettattr or getattribute inside itself as in lazy recursive directory listing
例如这样的事情:
class DotTabLoader():
def __init__(self, basedir, loaderfun):
self._basedir = pathlib.PosixPath(basedir)
self._loaderfun = loaderfun
self._list = list(self._basedir.glob('*/'))
self._names = [x.name.split('=')[1] for x in self._list]
self._names_dict = dict(zip(self._names, range(self._names)))
def __dir__(self):
return self._names
def __getattribute__(self, name):
# how to access self._list etc here?
return super().__getattribute__(name)
无限递归会出错。
更新:
正确的方法是这样的:
class DotTabLoader():
def __init__(self, basedir, loaderfun):
self._basedir = pathlib.PosixPath(basedir)
self._loaderfun = loaderfun
self._list = list(self._basedir.glob('*/'))
self._names = [x.name.split('=')[1] for x in self._list]
self._names_dict = dict(zip(self._names, range(len(self._names))))
def __dir__(self):
return self._names + super().__dir__()
def __getattr__(self, name):
try:
ind = self._names_dict[name]
basedir = self._list[ind]
return DotTabLoader(basedir, self._loaderfun)
except KeyError as e:
return super().__getattribute__(name)
最简单的方法是实现__getattr__
,只有在正常查找失败时才调用它。这意味着您可以在 __getattr__
实现中访问普通属性,而无需执行任何特殊操作,并且不会递归调用它,因为基础 class 查找成功。
def __getattr__(self, name):
return self._list[0] # works fine!
__getattribute__
更像是一种特殊情况,因为它是无条件调用的,而不是作为正常查找的回退。根据文档 (https://docs.python.org/3/reference/datamodel.html#object.getattribute)
如果你想访问 __getattribute__
中的属性而不调用你自己覆盖的 __getattribute__
实现,你需要调用 object
实现:
def __getattribute__(self, name):
return object.__getattribute__(self, '_list')[0]
例如这样的事情:
class DotTabLoader():
def __init__(self, basedir, loaderfun):
self._basedir = pathlib.PosixPath(basedir)
self._loaderfun = loaderfun
self._list = list(self._basedir.glob('*/'))
self._names = [x.name.split('=')[1] for x in self._list]
self._names_dict = dict(zip(self._names, range(self._names)))
def __dir__(self):
return self._names
def __getattribute__(self, name):
# how to access self._list etc here?
return super().__getattribute__(name)
无限递归会出错。
更新:
正确的方法是这样的:
class DotTabLoader():
def __init__(self, basedir, loaderfun):
self._basedir = pathlib.PosixPath(basedir)
self._loaderfun = loaderfun
self._list = list(self._basedir.glob('*/'))
self._names = [x.name.split('=')[1] for x in self._list]
self._names_dict = dict(zip(self._names, range(len(self._names))))
def __dir__(self):
return self._names + super().__dir__()
def __getattr__(self, name):
try:
ind = self._names_dict[name]
basedir = self._list[ind]
return DotTabLoader(basedir, self._loaderfun)
except KeyError as e:
return super().__getattribute__(name)
最简单的方法是实现__getattr__
,只有在正常查找失败时才调用它。这意味着您可以在 __getattr__
实现中访问普通属性,而无需执行任何特殊操作,并且不会递归调用它,因为基础 class 查找成功。
def __getattr__(self, name):
return self._list[0] # works fine!
__getattribute__
更像是一种特殊情况,因为它是无条件调用的,而不是作为正常查找的回退。根据文档 (https://docs.python.org/3/reference/datamodel.html#object.getattribute)
如果你想访问 __getattribute__
中的属性而不调用你自己覆盖的 __getattribute__
实现,你需要调用 object
实现:
def __getattribute__(self, name):
return object.__getattribute__(self, '_list')[0]