我有一个类,其中方法首先需要验证属性是否存在,否则调用函数来计算它。然后,确保该属性不是None
,它会对其执行一些操作。我可以看到两种略有不同的设计选择:
class myclass():
def __init__(self):
self.attr = None
def compute_attribute(self):
self.attr = 1
def print_attribute(self):
if self.attr is None:
self.compute_attribute()
print self.attr
和
class myclass2():
def __init__(self):
pass
def compute_attribute(self):
self.attr = 1
return self.attr
def print_attribute(self):
try:
attr = self.attr
except AttributeError:
attr = self.compute_attribute()
if attr is not None:
print attr
在第一个设计中,我需要确保所有类属性都提前设置为None
,这可能会变得冗长,但也会澄清对象的结构。
第二种选择似乎是更广泛使用的选择。然而,对于我的目的(与信息理论相关的科学计算),使用try except
块到处都可能有点过分,因为这个类并没有真正与其他类交互,它只需要数据并计算一堆的东西。
答案 0 :(得分:0)
首先,您可以使用hasattr
检查对象是否具有属性,如果属性存在,则返回True
。
hasattr(object, attribute) # will return True if the object has the attribute
其次,您可以在Python中自定义属性访问,您可以在此处阅读更多相关信息:https://docs.python.org/2/reference/datamodel.html#customizing-attribute-access
基本上,您可以覆盖__getattr__
方法来实现此目的,例如:
class myclass2(): def init (个体经营): 通
def compute_attr(self):
self.attr = 1
return self.attr
def print_attribute(self):
print self.attr
def __getattr__(self, name):
if hasattr(self, name) and getattr(self, name)!=None:
return getattr(self, name):
else:
compute_method="compute_"+name;
if hasattr(self, compute_method):
return getattr(self, compute_method)()
确保您只使用getattr
来访问__getattr__
中的属性,或者您最终会获得无限递归
答案 1 :(得分:-1)
基于the answer jonrsharpe linked,我提供了第三种设计选择。这里的想法是MyClass
的客户端或MyClass
本身的代码都不需要特殊的条件逻辑。相反,装饰器应用于执行属性(假设成本高昂)计算的函数,然后存储该结果。
这意味着昂贵的计算是懒惰地进行的(仅当客户端试图访问该属性时)并且只执行一次。
def lazyprop(fn):
attr_name = '_lazy_' + fn.__name__
@property
def _lazyprop(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, fn(self))
return getattr(self, attr_name)
return _lazyprop
class MyClass(object):
@lazyprop
def attr(self):
print('Generating attr')
return 1
def __repr__(self):
return str(self.attr)
if __name__ == '__main__':
o = MyClass()
print(o.__dict__, end='\n\n')
print(o, end='\n\n')
print(o.__dict__, end='\n\n')
print(o)
<强>输出强>
{}
Generating attr
1
{'_lazy_attr': 1}
1
修改强>
将Cyclone's answer应用于OP的上下文:
class lazy_property(object):
'''
meant to be used for lazy evaluation of an object attribute.
property should represent non-mutable data, as it replaces itself.
'''
def __init__(self, fget):
self.fget = fget
self.func_name = fget.__name__
def __get__(self, obj, cls):
if obj is None:
return None
value = self.fget(obj)
setattr(obj, self.func_name, value)
return value
class MyClass(object):
@lazy_property
def attr(self):
print('Generating attr')
return 1
def __repr__(self):
return str(self.attr)
if __name__ == '__main__':
o = MyClass()
print(o.__dict__, end='\n\n')
print(o, end='\n\n')
print(o.__dict__, end='\n\n')
print(o)
输出与上述相同。