python - 覆盖 __getattr__ 导致递归
问题描述
我正在尝试创建一个包装类,然后覆盖__getattr__
,以便对不在包装类中的属性的请求传递到内部对象中。下面是一个玩具示例,我使用列表作为内部对象 -
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()
不在A
. 不幸的是,我正在进行某种递归并且HERE
被打印了很多次。我想要的可能吗?
解决方案
这个
return getattr(self.foo, name)
实际上是:
foo = self.foo
return getattr(foo, name)
现在self.foo
实际上称之为:
try:
return self._foo
其中,由于您的班级定义了__getattr__
并且 - 至少第一次调用self.foo
- 没有_foo
属性,调用self.__getattr__("_foo")
,调用self.foo
,等等等等等等......
简单的解决方案:确保self._foo
在之前定义(即在初始化程序中),而不是尝试在foo()
.
您还可以测试_foo
实例的dict中是否存在,但是如果它也是一个计算属性,那么这将破坏继承_foo
——这是否是一个问题取决于上下文和具体用例。
@property
def foo(self):
if '_foo' not in self.__dict__:
self._foo = [2, 1]
return self._foo
注意:我假设您创建了foo
一个计算属性以允许延迟初始化_foo
,否则它没有什么意义。如果是这种情况,您也可以非常简单地_foo
在初始化程序中创建一个标记值(通常None
,除非None
是此属性的有效值),并在foo()
.
推荐阅读
- scala - 从 spark scala 抛出错误中的外部路径读取属性文件
- google-cloud-vision - google cloud vision OCR 翻译错误
- sql - 使用 TSQL 如何使用自定义时间段创建运行总计
- python - Python Pandas - 选择 .contains 的值
- angular - RxJS Observables - 如何调节可观察的回报
- android - xml可绘制或以编程方式绘制?
- reactjs - 刷新页面后反应路由器传递的数据丢失
- python - 在具有多个 '\n' 的字符串中查找子字符串
- unit-testing - 想模拟 DynamoHttpServletRequest 以通过 junit /mockito 中的测试属性
- apache-kafka - 如何在 Kafka 流聚合期间发布事件?