【发布时间】:2015-10-17 10:45:50
【问题描述】:
我对 python 中的封装嵌套属性有一些疑问。让我们假设几个类: 这里我们有一个主类(DataWrapper),其中包括另外两个类:InnerWrapper1 和 InnerWrapper2。两个内部包装器都包含两个属性。
class DataWrapper(object):
@property
def inner_wrapper1(self):
return self.__inner_wrapper1
@inner_wrapper1.setter
def inner_wrapper1(self, value):
self.__inner_wrapper1 = value
@property
def inner_wrapper2(self):
return self.__inner_wrapper2
@inner_wrapper2.setter
def inner_wrapper2(self, value):
self.__inner_wrapper2 = value
class InnerWrapper1(object):
@property
def property1(self):
return self.__property1
@property1.setter
def property1(self, value):
self.__property1 = value
@property
def property2(self):
return self.__property2
@property2.setter
def property2(self, value):
self.__property2 = value
class InnerWrapper2(object):
@property
def property3(self):
return self.__property3
@property3.setter
def property3(self, value):
self.__property3 = value
@property
def property4(self):
return self.__property4
@property4.setter
def property4(self, value):
self.__property4 = value
是否可以以某种方式覆盖 getattr 和 setattr 方法以实现以下封装?我想要实现的是从顶级类 DataWrapper 访问那些嵌套属性。
data_wrapper = DataWrapper()
data_wrapper.property1 = "abc"
...
var = data_wrapper.property2
...
我想到的第一件事是在 getattr 中执行 hasattr,但这给出了最大的递归深度...
这是一个完整的代码:
class DataWrapper(object):
def __init__(self):
self.inner_wrapper1 = InnerWrapper1()
self.inner_wrapper2 = InnerWrapper2()
@property
def inner_wrapper1(self):
return self.__inner_wrapper1
@inner_wrapper1.setter
def inner_wrapper1(self, value):
self.__inner_wrapper1 = value
@property
def inner_wrapper2(self):
return self.__inner_wrapper2
@inner_wrapper2.setter
def inner_wrapper2(self, value):
self.__inner_wrapper2 = value
def __setattr__(self, attribute, value):
#if attribute in {'innerwrapper1', 'innerwrapper2'}:
if attribute in ['inner_wrapper1', 'inner_wrapper2']:
return super(DataWrapper, self).__setattr__(attribute, value)
if hasattr(self.inner_wrapper1, attribute):
return setattr(self.inner_wrapper1, attribute, value)
elif hasattr(self.inner_wrapper2, attribute):
return setattr(self.inner_wrapper2, attribute, value)
def __getattr__(self, attribute):
try:
return getattr(self.inner_wrapper1, attribute)
except AttributeError: pass
try:
return getattr(self.inner_wrapper2, attribute)
except AttributeError: pass
class InnerWrapper1(object):
@property
def property1(self):
return self.__property1
@property1.setter
def property1(self, value):
self.__property1 = value
@property
def property2(self):
return self.__property2
@property2.setter
def property2(self, value):
self.__property2 = value
class InnerWrapper2(object):
@property
def property3(self):
return self.__property3
@property3.setter
def property3(self, value):
self.__property3 = value
@property
def property4(self):
return self.__property4
@property4.setter
def property4(self, value):
self.__property4 = value
def main():
data_wrapper = DataWrapper()
data_wrapper.property1 = "abc"
if __name__ == "__main__":
main()
【问题讨论】:
-
答案是“是的,这是可能的”。你在实施它时有什么问题吗?如果是这样,你能告诉我们你尝试了什么吗?
-
由于
__getattr__和__setattr__只使用属性名称,您需要考虑如何将属性访问路由到一个或另一个内部对象。您是想硬编码属性(if name in ('property1', 'property2'): # use first inner object、else:# ...)` 还是要动态测试属性? -
您可以edit您的问题添加您的尝试。如果这对您不起作用,会发生什么?
-
嗨,Martijn。感谢您的快速回复。我已经更新了我的问题:) 好吧,但是“使用”到底是什么意思?因为当我在 __ getattr __ 中调用 getattr 时出现最大递归深度错误
标签: python properties attributes nested encapsulation