[英]Use a class decorator to implement late-initialization
我正在使用一些需要連接到數據庫的類。 只有在執行實際操作時才需要連接。 我想延遲連接階段,直到確實需要它為止。 為此,我想做類似的事情:
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()
但使用裝飾器似乎是一種更易讀的解決方案。 可能嗎?
而不是嘗試裝飾需要連接的函數,而是使用屬性來獲取連接本身。
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()
至於直裝飾的例子,玩FJ的答案:
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
更加健壯,以便它可以正確地運行函數和靜態方法以及類和實例方法。
我喜歡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()
類似於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
的定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.