我正在创建一个装饰器来缓存可能抛出异常的昂贵函数的值,我想记录我们是否到达了初始化值的点。截至目前,我只是将该值初始化为“奇数”字符串 new_val = "__THIS_IS_UNINITIALIZED__"
但感觉很脏。
我想知道将 is
与自定义类(什么都不做)一起使用是否安全。
这是我现在拥有的:
class Cache:
_cached = {}
@staticmethod
def cache(prefix):
def wrapper(wrapped):
def inner(self, *args, **kwargs):
new_val = "__THIS_IS_UNINITIALIZED__"
key = Cache.make_key(*args, **kwargs)
if key in Cache._cached:
print("cache hit")
return Cache._cached[key]
print("cache miss")
try:
# This can throw exceptions
new_val = wrapped(self, *args, **kwargs)
# Something below this can ALSO throw
# exceptions, but the value has been
# initialized at this point.
except:
if new_val == "__THIS_IS_UNINITIALIZED__":
print("we never got to initialize :_( ")
else:
Cache._cache[key] = new_val
return inner
return wrapper
我想知道我是否可以使用 if is Class
而不是 if new_val == "__THIS_IS_UNINITIALIZED__"
像这样:
class Uninitialized:
pass
class Cache:
_cached = {}
@staticmethod
def cache(prefix):
def wrapper(wrapped):
def inner(self, *args, **kwargs):
new_val = Uninitialized
key = Cache.make_key(*args, **kwargs)
if key in Cache._cached:
print("cache hit")
return Cache._cached[key]
print("cache miss")
try:
# This can throw exceptions
new_val = wrapped(self, *args, **kwargs)
# Something below this can ALSO throw
# exceptions, but the value has been
# initialized at this point.
except:
if new_val is Uninitialized:
print("we never got to initialize :_( ")
else:
Cache._cache[key] = new_val
return inner
return wrapper
@staticmethod
def make_key(*args, **kwargs):
positional = ':'.join([str(s) for s in args])
kw = ':'.join('%s=%s' % kf for kv in kwargs.items())
return ':'.join([positional, kw])
class Test:
def __init__(self):
self.foo = 'hi'
@Cache.cache('api')
def test_cache(self, a, b):
raise Exception("foo")
if __name__ == "__main__":
t = Test()
t.test_cache(1, 2)
使用字符串 "__THIS_IS_UNINITIALIZED__"
到目前为止工作正常(并且在可预见的将来也将工作正常)。老实说,这主要是出于学习目的。
提前谢谢你。
最佳答案
标准的习惯用法是本质上做你所做的,但是创建一个 object
的实例,而不是为这样的哨兵定义一个新类。
Uninitialized = object()
因为你的类语句等同于
Uninitialized = type("Uninitialized", (object,), {})
唯一的区别是我实例化了 object
而不是 type
。
更新(通过 Sentinel object and its applications? ):自定义类的实例可以提供更有用的表示,如 the dataclasses
module 中的示例所示:
>>> from dataclasses import MISSING
>>> repr(MISSING)
'<dataclasses._MISSING_TYPE object at 0x10baeaf98>'
>>> repr(object())
'<object object at 0x10b961200>'
定义一个新类可以让您将类名用作简短的诊断消息或哨兵用途的描述。
关于python - 使用 `is (CustomClass)` 可以安全地检测 Python 中的未初始化值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55696875/