簡體   English   中英

使用類裝飾器來實現后期初始化

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM