1

私はこのような機能を持っています:

def foo(bar):
    ...

barこれで、Djangoレコードまたはレコードを指すスラッグのいずれかになります。実際のレコードが手元にあるときにこの関数を呼び出すことができるように、または文字列としてのみ使用可能なバー(データベースから取得)を持つより一般的な関数からこれを呼び出すことができるように、この柔軟性が必要です。

私は次のようなことができることに気づきました。

def foo(bar):
    try:
        bar.pk
    except AttributeError:
        bar = Bar.objects.get(slug=bar)
    ...

しかし、これはまったくエレガントではないようです。

可能であれば、isinstanceの使用を避けたいと思います。

4

3 に答える 3

5

定義上、ダックタイピングを使用していません。ダックタイピングは、「それがアヒルのように話し、アヒルのように見えるなら、それはアヒルだ」と言っています。

Duck Typingは、完全に異なるクラスの2つのオブジェクトをメソッドに渡して、両方が同じメソッド/属性を実装する(または欠落しているものを適切に処理する)ために機能させることができることを意味します。これは、メソッドが取得するタイプを気にすることはなく、渡すオブジェクトが使用することを期待する属性を持っていることを意味します。

あなたの場合、オブジェクトを渡すこともあれば、そのオブジェクトを検索するために使用できる文字列を渡すこともあります。これはダックタイピングとは何の関係もありません。

isinstanceはこれを解決する正しい方法です。この場合、これが問題を解決するための最も明確な方法です。他のものはより複雑になり、理解するのが難しくなります。利点はありません。属性またはhasattrでtry/exceptを使用することもできますが、それにより、将来の開発者は他の何よりも混乱する可能性があります。ダックタイピングは、特定の関数に一致するようにさまざまなサブクラスをキャストする代わりに使用できる優れた機能ですが、この場合、ダックタイピングは適用されません。

要するに。isinstanceを使用するだけです。あなたの場合、それはそれを行う正しい(pythonic)方法です。

于 2012-04-03T23:05:20.840 に答える
1

それがそれを処理するひどい方法であるかどうかはわかりませんが、私が同様のことをしたいのであれば、私はおそらく使用するでしょうhasattr

def foo(bar):
    if hasattr(bar,"pk"):
        bar.pk
    else:
        # I include the str in case some other object with a __str__ happens
        # to come through.
        bar = Bar.objects.get(slug=str(bar))
于 2012-04-03T22:07:07.813 に答える
0

これは、同じことをしたい他の機能に役立つ別の方法です。使用しているモデルの名前は「アイテム」であると想定します。

def slug_resilient_decorator(class_type):

    def slug_resilient_wrapper(obj):

            if obj.has_attr('pk'):
                    return obj
            else:
                    return class_type.objects.get(slug=obj)

    return wrapper

@slug_resilient_decorator(Item)
def slug_resilient_detail_view(obj):

    ...
于 2012-04-04T01:45:48.813 に答える