3

免責事項:この質問は宿題に関連しています。私は解決策を期待していませんが、何が求められているのか、そしてこの宿題の練習の(可能な)有用性についてのより良い理解を望んでいます。

この質問は、PythonのMySQLdbモジュールの使用と、タプルのタプル(MySQLdbのデフォルトのように)の代わりに結果セット(および場合によってはその行)をより適切に表現する方法についてのレッスンの後に尋ねられました。

問題は次のとおりです。build_row関数によって返されるDataRowクラスが別のメソッドを持つようにclassFactory.pyソースコードを変更します。

retrieve(self, curs, condition=None)

selfは(通常どおり)メソッドが呼び出されているインスタンスであり、cursは既存のデータベース接続上のデータベースカーソルであり、condition(存在する場合)は、受信したすべての行に当てはまる必要がある条件の文字列です。取得メソッドはジェネレーターである必要があり、完全に使い果たされるまで結果セットの連続する行を生成します。各行は、DataRowタイプの新しいオブジェクトである必要があります。

def build_row(table, cols):
    """Build a class that creates instances of specific rows"""
    class DataRow:
        """Generic data row class, specialized by surrounding function"""
        def __init__(self, data):
            """Uses data and column names to inject attributes"""
            assert len(data)==len(self.cols)
            for colname, dat in zip(self.cols, data):
                setattr(self, colname, dat)
        def __repr__(self):
            return "{0}_record({1})".format(self.table, ", ".join(["{0!r}".format(getattr(self, c)) for c in self.cols]))
    DataRow.table = table
    DataRow.cols = cols.split()
    return DataRow
  1. 関数定義内にクラスを作成する目的は何ですか?これは一般的にプロの開発者によって行われますか?もしそうなら、利点は何ですか?
  2. データベースカーソルがメソッドの(明示的な)引数であるのはなぜretrieveですか?データベースカーソルは、このスクリプトの範囲外で参照されるべきではありませんか(データベース接続が確立されたとき)?
  3. (現在)build_row関数は2つの引数(tableおよび)を受け入れcols、(例として)「exampleTable_record(fieldA、fieldB、fieldC)」のような文字列を返すと言うのは正しいですか?
  4. メソッドが正常に追加されたらretrieve、何がbuild_row返されると期待できますか?

前に触れたように、なぜメソッドを追加するように求められているのかがわかっていれば、retrieveこの問題をどのように攻撃するかについてより良いアイデアがあるかもしれません。

4

3 に答える 3

3
  1. これはファクトリデザインパターンと呼ばれます...この場合、クラスのインスタンス化をクラスを含むメソッドに強制するだけです...これにより、次の時点でテーブルと列の名前属性を設定する必要があります。インスタンス化...retrieveを呼び出しようとしたときに適切にインスタンス化されていないと、エラーが発生する可能性があります...
  2. データベースをクエリするには、カーソルオブジェクトが必要です。
  3. はい、しかしそれは戻り、DataRowクラスは文字列ではありません...これは文字列表現を持っています
  4. データを持つデータ行..。

ここにファクトリデザインパターンの説明へのリンクがあります なぜ抽象ファクトリデザインパターンが必要なのですか?

取得関数の例

@classmethod #if this is a classmethod
def retrieve(self, curs, condition=None):
        if condition:
           curs.execute("SELECT * FROM {0} WHERE {1}".format(self.table,condition)
        else:
           curs.execute("SELECT * FROM {0}".format(self.table)
        for row in curs.fetchall():
            yield DataRow(row)

その後、あなたは次のようなことをします

my_users = build_row("users",["username","password","avatar"])
my_users = my_users()  #if you need to operate on an instance.... but class method would be better
#users is the name of a table already in our database, whose columns are username,password, and avatar
db=sqlite3.connect("some_database.sql")
for user in my_users.retrieve(db.cursor(),"username='bob'"):
    print user #something like users_record({'username':'bob','password':'123%gw','avatar':None)
    print user.username #bob
    print user.avatar #None
    print user.password #whatever
    print user.blah #Error!!!!
于 2012-10-22T02:42:24.773 に答える
2

2)データベースカーソルがretrieveメソッドの(明示的な)引数であるのはなぜですか?データベースカーソルは、このスクリプトの範囲外で参照されるべきではありませんか(データベース接続が確立されたとき)?

カプセル化。グローバルマジック変数に依存すると、依存関係が作成されますが、可能な場合は回避する必要があります。アプリケーションで同時に複数のカーソルがアクティブになっている場合や、別々の接続を介して2つのデータベースと通信している場合があることを考慮してください。

引数を渡すと、コードのテストも簡単になります。グローバル変数を変更しなくても、モッククラスなどを渡すことができます。

于 2012-10-27T21:35:06.363 に答える
1

あなたが持っているのは、これを専門的に使用できる例です。この関数build_rowは、特定のテーブルと列のデータを処理するのに適したクラスを返すクラスファクトリです。

この特定のケースでは、個人的にファクトリパターンを使用しなかったでしょうが、それは機能します。

したがって、このコードが何をしているのかを説明するために、基本的に、関数呼び出しからのテーブルと列を使用するクラスを作成します。self.colsコードに気づき、存在しself.tableているが、実際にはの一部ではないDataRow場合、後でコードにアタッチされます。これは、この方法でクラスを作成する柔軟性を示しています。

build_row関数が実際に返すのはクラスです!このクラスは、データベースからデータを取得するために使用する必要があります...これは、割り当てのために構築する必要がある部分です。tableselectステートメントで(テーブル名)を使用する必要があります。また、 cols...基本的に関数(これは作成しません)が実行する必要があります。

SELECT <PUT THE `cols` HERE> FROM `table`;

結果を返します。これはあなたを動かすのに十分なはずです。

于 2012-10-25T06:01:04.143 に答える