我正在使用一些需要连接数据库的类。只有在执行实际操作时才需要连接。我想延迟连接阶段,直到确实需要它为止。为此,我想做类似的事情:
class MyClass
def __init__(self):
self.conn = None
def connect(self):
if self.conn : return
self.conn = ConnectToDatabase()
@connect
def do_something1(self):
self.conn.do_something1()
@connect
def do_something2(self):
self.conn.do_something2()
但我不知道如何为班级定义connect
装饰器。
我当然可以这样做:
def do_something1(self):
self.connect()
self.conn.do_something1()
但使用装饰器似乎是一种更具可读性的解决方案。有可能吗?
答案 0 :(得分:5)
不是试图装饰需要连接的函数,而是使用属性来获取连接本身。
class MyClass(object):
def __init__(self):
self._conn = None
@property
def conn(self):
if self._conn is None:
self._conn = ConnectToDatabase()
return self._conn
def do_something1(self):
self.conn.do_something1()
def do_something2(self):
self.conn.do_something2()
至于一个直的装饰者的例子,玩F.J的回答:
def prerequisite(prerequisite_function, *pre_args, **pre_kwargs):
def wrapper(func):
def wrapped(self, *args, **kwargs):
prerequisite_function(self, *pre_args, **pre_kwargs)
return func(self, *args, **kwargs)
return wrapped
return wrapper
class MyClass(object):
def __init__(self):
self.conn = None
def connect(self):
if self.conn is None:
self.conn = ConnectToDatabase()
@prerequisite(connect)
def do_something(self):
self.conn.do_something()
您还可以通过创建描述符使prerequisite
更加健壮,以便它可以正常运行函数和静态方法以及类和实例方法。
答案 1 :(得分:2)
我喜欢sr2222使用属性获取连接的方法,但是这里有一个装饰器的方法可能很有用或至少提供信息(functools.wraps()
的使用是可选的):
import functools
def require_connection(f):
@functools.wraps(f)
def wrapped(self, *args, **kwargs):
self.connect()
return f(self, *args, **kwargs)
return wrapped
class MyClass(object):
def __init__(self):
self.conn = None
def connect(self):
if self.conn : return
self.conn = ConnectToDatabase()
@require_connection
def do_something1(self):
self.conn.do_something1()
@require_connection
def do_something2(self):
self.conn.do_something2()
答案 2 :(得分:2)
与sr2222的解决方案类似,但称之为:cached_property
。
代码更紧凑,使用可重用的构建块,在我看来更具可读性。
class MyClass(object):
@cached_property
def conn(self):
return ConnectToDatabase()
def do_something1(self):
self.conn.do_something1()
def do_something2(self):
self.conn.do_something2()
找到cached_property
的定义here。