lib*_*lib 7 python inheritance properties
我有一堂课,比如:
class Parent(object):
def __init__(self, a1 = None, a2 = None):
someInitialization()
self.a1 = a1
self.a2 = a2
def coolMethod(self):
return dosomething(self.a2)
Run Code Online (Sandbox Code Playgroud)
这么说吧
编辑我的实际约束并不是那么严格,但我问这个问题也是为了更好地理解类属性、方法等。
我正在使用最简单的解决方案,无需初始化继承:
class Child(Parent):
_propertiesCache = {'a1':None,'a2':None}
def _initProperty(self, propertyName):
value = self._propertiesCache[propertyName]
if value is None:
self._propertiesCache[propertyName]=expensiveFunction(self.b, propertyName)
return self._propertiesCache[propertyName]
@property
def a1(self):
return self._initProperty('a1')
@property
def a2(self):
return self._initProperty('a2')
def __init__(self,b):
self.b = b
someInitialization()
Run Code Online (Sandbox Code Playgroud)
有没有办法正确调用父类的初始化?如果我使用super(Child,self).__init__()我得到AttributeError: can't set attribute。我试图覆盖__new__但我总是错过一些东西
class Child(Parent):
_propertiesCache = {'a1':None,'a2':None}
@classmethod
def _initProperty(cls, propertyName):
value = cls._propertiesCache[propertyName]
if value is None:
cls._propertiesCache[propertyName] = someTimeConsumingFunctionThatIDontWantToCallAtInitialization(propertyName)
return cls._propertiesCache[propertyName]
@property
def a1(self):
return self._initProperty('a1')
@property
def a2(self):
return self._initProperty('a2')
def __new__(cls):
super(Child,cls).__new__(cls)
return cls
def __init__(self,b):
self.b = b
super(Child,self).__init__(a1=self.a1, a2=self.a2)
Run Code Online (Sandbox Code Playgroud)
给我:
>>c = Child();c.a1
<property at 0x3aa4228>
>>c.a1.fget(c)
"ValueOfa1"
Run Code Online (Sandbox Code Playgroud)
不要调用您的方法,而是_initProperty调用它,__getattr__以便每次在应存储的正常位置(属性字典、类字典等)中找不到该属性时都会调用该方法,然后在第一次尝试访问该属性时调用该方法被初始化。
确保不要在 Parent 初始化中设置它们,也许只有在它们不是 None 时才设置它们:
class Parent:
def __init__(self,a1=None,a2=None):
if a1 is not None:
self.a1 = a1
if a2 is not None:
self.a2 = a2
Run Code Online (Sandbox Code Playgroud)
为了与错误保持一致,AttributeError如果属性不存在,您将需要引发,而不是让其KeyError通过,并且可能添加对常规属性字典中的值的引用,以便不需要运行__getattr__每次:
_propertiesCache = {'a1':None,'a2':None}
def __getattr__(self, propertyName):
if propertyName not in self._propertiesCache:
raise AttributeError(propertyName)
value = self._propertiesCache[propertyName]
if value is None:
value = self._propertiesCache[propertyName]=expensiveFunction(self.b, propertyName)
setattr(self,propertyName,value)
return value
Run Code Online (Sandbox Code Playgroud)
无论以何种方式实现这一点,您都需要确保:
该属性直到第一次使用时才设置(此时__getattr__使用)