4

データベースに接続する必要があるいくつかのクラスを使用しています。接続は、実際のアクションを実行するときにのみ必要です。本当に必要になるまで接続フェーズを遅らせたい。そのために、私はこれに似た何かをしたい:

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()

しかし、デコレータを使用すると、より読みやすいソリューションのようです。出来ますか?

4

3 に答える 3

6

接続を必要とする関数を装飾しようとするのではなく、プロパティを使用して接続自体を取得します。

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また、関数や静的メソッドだけでなく、クラスやインスタンス メソッドに対しても正しく動作できるように記述子を作成することで、より堅牢にすることもできます。

于 2013-03-13T17:24:21.607 に答える
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ここにあります。

于 2013-03-13T18:01:04.393 に答える
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()
于 2013-03-13T17:35:52.443 に答える