覆盖 __getattr__ 导致递归
Overwriting __getattr__ causing recursion
我正在尝试创建一个包装器 class,然后覆盖 __getattr__
,以便将不在包装器 class 中的属性请求传递到内部对象中。下面是一个玩具示例,其中我使用列表作为内部对象 -
class A(object):
def __init__(self):
pass
def __getattr__(self, name):
print 'HERE'
return getattr(self.foo, name)
@property
def foo(self):
try:
return self._foo
except:
self._foo = [2, 1]
return self._foo
我想做类似的事情
a = A()
a.sort() # initializes and sorts _foo
print a.foo
打印 [1, 2]
最后,我需要 _foo
在第一次调用 foo
或有人试图从 A()
中获取不在 [=18= 中的属性时进行初始化].不幸的是,我正在进行某种递归并且 HERE
被打印了很多次。我想要的可能吗?
这个
return getattr(self.foo, name)
实际上是:
foo = self.foo
return getattr(foo, name)
现在self.foo
实际调用这个:
try:
return self._foo
,因为你的 class 定义了 __getattr__
并且 - 至少第一次调用 self.foo
- 没有 _foo
属性,调用 self.__getattr__("_foo")
,调用 self.foo
,等等等等......
简单的解决方案:确保 self._foo
之前定义(即在初始化程序中),而不是试图在 foo()
中定义它。
你也可以在实例的字典中测试 _foo
的存在,但是如果 _foo
也是一个计算属性,那将破坏继承——这是否是一个问题取决于上下文和具体用例。
@property
def foo(self):
if '_foo' not in self.__dict__:
self._foo = [2, 1]
return self._foo
注意:我假设您将 foo
设为计算属性以允许 _foo
的延迟初始化,否则它毫无意义。如果是这种情况,您也可以非常简单地在初始化程序中使用标记值创建 _foo
(通常是 None
,除非 None
是此属性的有效值)并给它它在 foo()
.
中具有真正的价值
您需要先将 _foo
设置为某种值,即使它不是真实值。像这样:
class A(object):
_foo = None
def __init__(self):
pass
def __getattr__(self, name):
print 'HERE'
return getattr(self.foo, name)
@property
def foo(self):
if self._foo is None:
self._foo = [2, 1]
return self._foo
我正在尝试创建一个包装器 class,然后覆盖 __getattr__
,以便将不在包装器 class 中的属性请求传递到内部对象中。下面是一个玩具示例,其中我使用列表作为内部对象 -
class A(object):
def __init__(self):
pass
def __getattr__(self, name):
print 'HERE'
return getattr(self.foo, name)
@property
def foo(self):
try:
return self._foo
except:
self._foo = [2, 1]
return self._foo
我想做类似的事情
a = A()
a.sort() # initializes and sorts _foo
print a.foo
打印 [1, 2]
最后,我需要 _foo
在第一次调用 foo
或有人试图从 A()
中获取不在 [=18= 中的属性时进行初始化].不幸的是,我正在进行某种递归并且 HERE
被打印了很多次。我想要的可能吗?
这个
return getattr(self.foo, name)
实际上是:
foo = self.foo
return getattr(foo, name)
现在self.foo
实际调用这个:
try:
return self._foo
,因为你的 class 定义了 __getattr__
并且 - 至少第一次调用 self.foo
- 没有 _foo
属性,调用 self.__getattr__("_foo")
,调用 self.foo
,等等等等......
简单的解决方案:确保 self._foo
之前定义(即在初始化程序中),而不是试图在 foo()
中定义它。
你也可以在实例的字典中测试 _foo
的存在,但是如果 _foo
也是一个计算属性,那将破坏继承——这是否是一个问题取决于上下文和具体用例。
@property
def foo(self):
if '_foo' not in self.__dict__:
self._foo = [2, 1]
return self._foo
注意:我假设您将 foo
设为计算属性以允许 _foo
的延迟初始化,否则它毫无意义。如果是这种情况,您也可以非常简单地在初始化程序中使用标记值创建 _foo
(通常是 None
,除非 None
是此属性的有效值)并给它它在 foo()
.
您需要先将 _foo
设置为某种值,即使它不是真实值。像这样:
class A(object):
_foo = None
def __init__(self):
pass
def __getattr__(self, name):
print 'HERE'
return getattr(self.foo, name)
@property
def foo(self):
if self._foo is None:
self._foo = [2, 1]
return self._foo