1

私は SQLAlchemy を使用していますが、__new__関数について読んだところです。ここにある他の投稿も読んだ__new__ので、 との違い__init__、それらが呼び出される順序、およびそれらの目的と、私にとっての主なメッセージは次のとおりでした: Use __new__to control the creation of a new instance .

そのことを念頭に置いて、SQLAlchemy を使用してインスタンスを取得したい場合 (そして、インスタンスが存在しない場合はインスタンスを作成します。たとえば、User オブジェクトを取得する場合、通常は次のようにします。

user = DBSession.query(User).filter(User.id==user_id).first()
if not user:
    user = User()

これにより、現在のユーザーが返されるか、新しいユーザーが返されます。魔法についての新しい知識を得た今、私は次のようなことが良い考えだと思いました:

user = User(id=user_id)

そして、私のデータベース クラスでは、次のように呼び出します。

def __new__(cls, id=0):
    if id:
        user = DBSession.query(User).filter(User.id==id).first()
    if not id or not user:
        user = super(User, cls).__new__(cls, id=id)
    return user

現在、このコードは簡単なドラフトにすぎません (たとえば、super への呼び出しが欠落しています) が、アイデアを明確に指摘する必要があります。

今私の質問:これは良い習慣ですか、それとも避けるべきですか? 避けるべき場合: なぜですか?

4

3 に答える 3

2

あなたの質問とコメントに基づいて、これをしないことをお勧めします。なぜなら、そうする理由がないようで、自分が何をしているのか理解していないようだからです。

あなたは特定のコードを入れると言います__new__。しかし、__new__何の?あなたがこれを持っている場合:

class User(Base):
    def __new__(cls, id=0):
        if id:
            user = DBSession.query(User).filter(User.id==id).first()
        if not user:
            user = User()
        return user

. . . Userインスタンスを作成__new__しようとすると、別のインスタンスを作成しようとするなど、無限再帰につながります。

を使用してuser = User.__init__()も何も解決しません。 __init__常に None を返すため、単に None オブジェクトを作成しようとしています。

の適切な使用例__new__は、 を実行してクラスをインスタンス化するときに返されるオブジェクトの種類を変更する場合ですSomeClass()。これを行う必要があることはまれです。最も一般的なケースは、 などの組み込み型を模倣するユーザー定義クラスを作成する場合ですがdict、その場合でも、これを行う必要がない場合があります。

コードが をオーバーライドしなくても機能する場合は、 をオーバーライド__new__しないでください__new__。別の方法では解決できない特定の問題やタスクがある場合にのみ、オーバーライドしてください。

于 2012-08-26T21:17:28.870 に答える
0

From what I see and unterstand, there is no reason why not to put your code into __init__ instead of __new__. There are only a few and very limited - but valid - uses cases for __new__ and you should really know what you are doing. So unless you have a very good reason, stick with __init__.

于 2012-08-26T20:42:30.503 に答える
0

最初の例 (戻り値をチェックする) と 2 番目の例 (コンストラクターをすぐに使用する) の間には、非常に明確な違いがあります。そしてその違いは自由変数です: DBSession.

場合によっては、この違いは興味深いものではありません。データベースの永続性のために sqlalchemy マップ オブジェクトのみを使用している場合。そして、sqlalchemy.orm.scopedsession許可されているコンテキストでのみ (スレッドごとに正確に 1 つのセッション)。その場合、違いはあまり興味深いものではありません。

これらの条件が両方とも成り立つことは珍しく、どちらも成り立たないことがよくあります。

これを行うことにより、オブジェクトがデータベース永続性のコンテキスト外で使用できなくなります。モデルをデータベースから切断することで、アプリケーションは「このオブジェクトがこの属性を持っていたらどうなるか?」などの質問に答えることができます。「このオブジェクトにはこの属性がありますか?」などの質問に加えて、これは、データベースの値を python オブジェクトとしてマップする理由の核心になりdictます。これにより、単なる属性のバッグである s としてではなく、興味深い動作を持つことができます。

たとえば、通常のデータベース永続ログインの使用に加えて、ユーザーが OAuth などを使用してサイトにログインできるようにすることができます。ユーザーの名前とパスワードをデータベースに永続化する必要はありませんが、アプリケーションの残りの部分が機能するようにオブジェクトを作成するUser必要があります (ユーザーの gravatar がテンプレートに表示されるようにするため)。

デフォルトで特定のデータベース コンテキストに暗黙的にアクセスするというもう 1 つの問題は、通常はお勧めできません。アプリケーションが成長するにつれて、データベースがより複雑になる方法を管理する必要があります。オブジェクトは複数のデータベース ホストに分割できます。同じスレッドで複数の同時トランザクションを管理している場合があります。キャッシュのパフォーマンス上の理由から、特定のセッションを再利用したい場合があります。sqlalchemySessionクラスは、これらすべての特殊性に対処するために存在します。最も一般的なパターンを使用しているときでも、それらを明示的に管理します。時折の変動への対処がはるかに簡単になります。

Web アプリでの非常に一般的な例は、スタートアップ コードです。アプリケーションがリクエストを処理する準備が整う前に、データベースからいくつかの重要なデータを引き出す必要がある場合があります。しかし、サービスを提供するリクエストがないため、データベース接続はどこから来るのでしょうか? 起動したらどうやって消すの?これらの質問は通常、明示的に管理されたセッションでは問題になりません。

于 2012-08-26T21:04:20.370 に答える