Python 将属性与try和except一起使用的正确方法
我有一些类的属性设置为Python 将属性与try和except一起使用的正确方法,python,properties,Python,Properties,我有一些类的属性设置为@propertydecorator。它们使用内部的try和except子句充当getter和setter。若并没有设置该属性,它将从数据库中获取数据,并使用它从其他类中恢复对象。我尽量使示例简短,但用于实例化属性对象的代码对于每个属性都有点不同。他们的共同点是尝试,除了一开始 class SubClass(TopClass): @property def thing(self): try: return self.
@property
decorator。它们使用内部的try和except子句充当getter和setter。若并没有设置该属性,它将从数据库中获取数据,并使用它从其他类中恢复对象。我尽量使示例简短,但用于实例化属性对象的代码对于每个属性都有点不同。他们的共同点是尝试,除了一开始
class SubClass(TopClass):
@property
def thing(self):
try:
return self._thing
except AttributeError:
# We don't have any thing yet
pass
thing = get_some_thing_from_db('thing')
if not thing:
raise AttributeError()
self._thing = TheThing(thing)
return self._thing
@property
def another_thing(self):
try:
return self._another_thing
except AttributeError:
# We don't have things like this yet
pass
another_thing = get_some_thing_from_db('another')
if not another_thing:
raise AttributeError()
self._another_thing = AnotherThing(another_thing)
return self._another_thing
...etc...
@property
def one_more_thing(self):
try:
return self._one_more_thing
except AttributeError:
# We don't have this thing yet
pass
one_thing = get_some_thing_from_db('one')
if not one_thing:
raise AttributeError()
self._one_more_thing = OneThing(one_thing)
return self._one_more_thing
我的问题是:这是一种正确的(如蟒蛇式)做事方式吗?在我看来,在所有内容之上添加“尝试除外”部分似乎有点尴尬。另一方面,它使代码保持简短。或者有更好的定义属性的方法吗?只要您至少使用Python 3.2,就可以使用
functools.lru\u cache()
decorator
import functools
class SubClass(TopClass):
@property
@functools.lru_cache()
def thing(self):
thing = get_some_thing_from_db('thing')
if not thing:
raise AttributeError()
return TheThing(thing)
一个快速运行的示例:
>>> import functools
>>> class C:
@property
@functools.lru_cache()
def foo(self):
print("Called foo")
return 42
>>> c = C()
>>> c.foo
Called foo
42
>>> c.foo
42
如果你有很多这样的东西,你可以结合装饰师:
>>> def lazy_property(f):
return property(functools.lru_cache()(f))
>>> class C:
@lazy_property
def foo(self):
print("Called foo")
return 42
>>> c = C()
>>> c.foo
Called foo
42
>>> c.foo
42
如果您仍然使用较旧版本的Python,则会有一个功能齐全的lru_缓存后端口,尽管在本例中,您调用它时没有传递任何参数,您可能会用更简单的东西替换它
@YAmikep询问如何访问lru\u cache
的cache\u info()
方法。它有点凌乱,但您仍然可以通过property对象访问它:
>>> C.foo.fget.cache_info()
CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
太棒了。实际上,我仍然使用2.7,但是ActiveState实现看起来很不错,很高兴知道它已经存在于Python3.2中。正如你所说,我可能会写一个更轻的版本。谢谢你,我将把这标记为一个答案。@Duncan:当使用lazy_属性装饰器时,我们如何访问cache_info()?由于属性包装functools.lru\u缓存,因此无法再访问该缓存<代码>c.foo.cache_info()不起作用。。Thanks@YAmikep我更新了我的答案,以显示一种方法来做到这一点。好的,谢谢。有一件事我不太明白:缓存在类上?然后它被所有实例共享?是否不可能为每个实例设置缓存?我想在实例的生命周期内缓存实例上的属性,但是如果我创建了多个实例,并且共享缓存已满,那么第一个实例的缓存值将被删除,对吗?ThanksIs
lazy_属性
是否真的而不仅仅是缓存?