[Python-ideas] Use iter() for defaults (was Re: function defaults and an empty() builtin)

Terry Reedy tjreedy at udel.edu
Sun May 22 01:41:20 CEST 2011


On 5/21/2011 5:48 PM, Terry Reedy wrote:

>> def query_sphinx(search_text, include=None, exclude=None):
>> if include is None:
>> include = {}
>> if exclude is None:
>> exclude = {}
>
> Since you are not mutating include and exclude, there is no point to
> this noise. I fact, I consider it wrong because it actually *misleads*
> other devs who would expect something put into each of them and
> returned. The proper way to write this is
>
> def query_sphinx(search_text, include={}, exclude={}):
>
> which documents that the parameters should be dicts (or similar) and
> that they are read only. You version implies that it would be ok to
> write to them, which is wrong.
>
>>
>> query = sphinxapi.client()
>>
>> for field, values in include.items():
>> query.SetFilter(field, values)
>> for field, values in exclude.items():
>> query.SetFilter(field, values, exclude=True)
>>
>> return query.query(search_text)

Here is back-compatible rewrite that expands the domain for 'include' 
and 'exclude' to iterables of key-value pairs. It both documents and 
ensures that query_sphinx() will do nothing but iterate through 
key-value pairs from the last two args.

def query_sphinx(search_text,
                  include=iter({}.values()),
                  exclude=iter({}.values())):
     if isinstance(include, dict):
         include = include.items()
     if isinstance(exclude, dict):
         exclude = exclude.items()

     query = sphinxapi.client()
     for field, values in include():
         query.SetFilter(field, values)
     for field, values in exclude():
         query.SetFilter(field, values, exclude=True)

     return query.query(search_text)

Lifting effectively constant expressions out of a loop is a standard 
technique. In this case, the 'loop' is whatever would cause repeated 
calls to the function without explicit args. The small define-time cost 
of the extra calls would eventually be saved at runtime by reusing the 
dict_valueiterators instead of creating equivalent ones over and over.

-- 
Terry Jan Reedy




More information about the Python-ideas mailing list