web-dev-qa-db-ja.com

python / djangoでのsetattrとオブジェクト操作の違い

私は次のモデルを持っています:

class Ticket(models.Model):
    title = models.CharField()
    merged_to = models.ForeignKey("self", related_name='merger_ticket', null=True, blank=True)
    looser_ticket = models.BooleanField(default=False)

モデルを操作する方法はいくつかあります。

最初

ticket = Ticket.objects.get(pk=1)
ticket.title = "This is edit title"
ticket.merged_to_id = 2
ticket.looser_ticket = True

2番目

ticket = Ticket.objects.get(pk=1)
setattr(ticket, "title", "Edit Title")
setattr(ticket, "merged_to_id", 2)
setattr(ticket, "looser_ticket", True)

私がものを操作しているとき、ブール値の更新のビューでは、最初の方法は機能しませんでしたが、2番目の方法は機能しました。 1番目と2番目の使用の違いは何ですか、いつ使用する必要がありますか?

ありがとう!

26
whatf

これは、Python質問の詳細です。

Pythonは非常に動的な言語です。事前に物事(クラス)をコーディングするか、Pythonを使用すると、実行時に完全に動的にクラスを作成できます。次の単純なベクトルクラスの例を検討してください。次のような事前クラス:

class MyVector(object):
    x = 0
    y = 0

または、次のようにしてクラスを動的に作成できます。

fields = {'x':0, 'y':0}
MyVector = type('MyVector', (object,), fields)

これらのメソッドの主な違いは、事前にクラス属性を知っているものに対して、想像できる2番目のメソッドについては、プログラムでfields辞書を作成できるため、完全に動的なクラス( es)。

したがって、事前にクラスの属性がわかっている場合は、オブジェクト表記を使用してクラス属性を設定できます。

instance.attribute = value

これは次と同等であることに注意してください。

instance.__setattr__(attribute, value)

ただし、事前に操作する必要があるクラス属性がわからないシナリオもあります。ここで、__setattr__関数を使用できます。ただし、推奨される方法ではありません。したがって、代わりにPythonの組み込みメソッドsetattrを使用することをお勧めします。これは、内部で__setattr__メソッドを呼び出します。

setattr(instance, attribute, value)

このアプローチを使用すると、事前にわからない属性を設定したり、一部のdictをループしてdictから値を設定したりすることもできます。

values = {
    'title': 'This is edit title',
    ...
}
for k, v in values.items():
    setattr(ticket, k, v)

通常の表記がうまくいかなかった理由がわかりません。これは、属性を設定するために使用した方法とはおそらく関係ありません。

35
miki725

事前にオブジェクトのプロパティがわかっている場合は、おそらく最初の方法を使用する必要があります。プロパティ値を直接割り当てるだけです。

2番目は、プロパティに動的に値を割り当てる必要がある場合に役立ちます。おそらく、ユーザーはいくつかの異なる属性の値を変更することができ、どの属性が事前に値を持つかがわからない場合は、動的に値を追加できます

possible_fields = ['title', 'looser_ticket']
ticket = Ticket.objects.get(pk=1)
for field in possible_fields:
  if request.GET.get(field):
     setattr(ticket, field, request.GET[field])

「機能しない」は、値の設定方法に依存していない可能性があります。後で変更を保存しますか?

9
dm03514