Хотя прошло много времени и было сказано много правильных вещей, нет ответа, который связывает оба эффекта.
У вас есть 2 эффекта:
+=
(как указано Scott Griffiths ) В классе foo
метод __init__
изменяет атрибут класса. Это потому, что self.bar += [x]
соответствует self.bar = self.bar.__iadd__([x])
. __iadd__()
для модификации места, поэтому он изменяет список и возвращает ссылку на него.
Обратите внимание, что экземпляр dict изменен, хотя это, как правило, не требуется, поскольку класс dict уже содержит одно и то же назначение , Таким образом, эта деталь почти незаметна - кроме случаев, когда вы делаете foo.bar = []
. Здесь экземпляры bar
остаются теми же благодаря сказанному факту.
Однако в классе foo2
используется bar
класса, но не затрагивается. Вместо этого к нему добавляется [x]
, образуя новый объект, так как здесь вызывается self.bar.__add__([x])
, который не изменяет объект. Результат помещается в экземпляр dict then, давая экземпляру новый список как dict, в то время как атрибут класса остается модифицированным.
Различие между ... = ... + ...
и ... += ...
также влияет на присвоения впоследствии :
f = foo(1) # adds 1 to the class's bar and assigns f.bar to this as well.
g = foo(2) # adds 2 to the class's bar and assigns g.bar to this as well.
# Here, foo.bar, f.bar and g.bar refer to the same object.
print f.bar # [1, 2]
print g.bar # [1, 2]
f.bar += [3] # adds 3 to this object
print f.bar # As these still refer to the same object,
print g.bar # the output is the same.
f.bar = f.bar + [4] # Construct a new list with the values of the old ones, 4 appended.
print f.bar # Print the new one
print g.bar # Print the old one.
f = foo2(1) # Here a new list is created on every call.
g = foo2(2)
print f.bar # So these all obly have one element.
print g.bar
Вы можете проверить идентичность объектов с помощью print id(foo), id(f), id(g)
(не забудьте дополнительные ()
s, если вы находитесь на Python3).
BTW: Оператор +=
называется «расширенным назначением» и, как правило, имеет целью сделать возможными модификации на месте.
Вам все еще нужно .all()
, чтобы получить список элементов вашего отношения:
for this one in attendees:
print(thisone.attendingmembers.all())
Btw, вы хотите получить все attendingmembers
или только те, которые имеют право calendar_id
?
attendees = Member.objects.filter(attendingmembers__calendar_id=id).prefetch_related('attendingmembers')
# return all Members having at least one attendingmember with calendar_id=id, and prefetch all of their attendingmembers
attendees = Member.objects.filter(attendingmembers__calendar_id=id).prefetch_related(Prefetch('attendingmembers', queryset=Attendee.objects.filter(calendar_id=id)))
# return all Members having at least one attendingmember with calendar_id=id, and prefetch their attendingmembers matching the filter
В документации показано, как использовать аргумент to_attr
в объектах Prefetch;)
.select_related
. Здесь вы хотите отфильтровать связанные объекты, поэтому, думаю, вам понадобитсяPrefetch
. Опять же, там должна помочь документация . – Moi 18 July 2018 в 16:39