Fix bugs in fields handling, and make it consistent.

The existing handling of fields is inconsistent in the three places it
appears: `EdgeIterator`, `AbstractCrudObject.get_by_ids` and
`AbstractCrudObject.remote_read`. The result varies between a string,
a list, None, or omitted from params.

This commit ensures that:

  1. In all cases, `params['fields']` will contain either a non-empty
     string, or will be omitted entirely.

  2. If fields is passed to a function, even an empty list, it will be
     respected rather than falling back to `get_default_read_fields`. This
     is accomplished by testing for `is None` rather than just a falsy
     value.

Additionally this uses a more common Python idiom for duplicating a dict,
using `dict(orig)` rather than `orig.copy()`.