Hi all,

I discovered that QuerySet supports the 'in' operator:

  myset = Articles.objects.filter(foo=bar)
  if someobject in myset:
      # etc.

The Python docs I could find imply (but don't state) that if there is 
no __contains__() method, but there is __getitem__(), then 
__getitem__() is called repeatedly, starting with zero, until 
IndexError, and it then does an 'in' on the resulting list.

That would be very inefficient with a QuerySet, but thankfully it 
appears from stepping through a debugger that that doesn't happen if 
you define __iter__() (as we have on QuerySet) - it actually calls 
__iter__() until StopIteration, and does 'in' on that list.

This means that the above code is pretty efficient - it does just one 
SQL query.

However, it could be slightly more efficient in some cases, because 
the entire QuerySet._result_cache does not necessarily need to be 
filled - we can stop if we find a match, saving us the work of 
building Model objects that might not be needed.

The plumbing to do this is all there already - we already optimize the 
__nonzero__ method in this way, by getting just the first result. It 
can of course be continued if the rest of the set is needed.

So, I'm thinking of implementing the __contains__ method to do this 
optimization.  Can anyone think of reasons why not?  I think the 'in' 
operator is perfectly well defined for QuerySets.  

I don't see this as something that should be documented as a normal 
way to do membership tests, as there will often be much more efficient 
ways to do it using ORM methods.  But, it is something that developers 
might do, and with the addition of the 'in' operator in the 'if' tag, 
it's something that template authors will be able to do.

An explicit __contains__ method also protects us against changes in 
Python which could produce quite different performance.

Regards,

Luke

-- 
"If something is hard, it's not worth doing." (Homer Simpson)

Luke Plant || http://lukeplant.me.uk/

--

You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.


Reply via email to