[英]Python design - initializing, setting, and getting class attributes
我有一個類,其中方法首先需要驗證屬性是否存在,否則調用函數來計算它。 然后,確保該屬性不是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
塊到處都可能有點過分,因為這個類並沒有真正與其他類交互,它只需要數據並計算一堆東西。
首先,您可以使用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 (self):pass
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__
的屬性,否則你最終會得到無限遞歸
基於jonrsharpe鏈接的答案 ,我提供了第三個設計選擇。 這里的想法是, 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
編輯
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)
輸出與上面相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.