Differences between indigo.Dict and python dict (and indigo.List and python list)The indigo.Dict and indigo.List classes are wrappers around internal dict and list objects used by Indigo server and clients. They provide python access to native Indigo instances directly, and allow an easy mechanism for plugins and scripts to access and store data in Indigo, such as preferences, device properties, etc.
The behavior of indigo.Dict and indigo.List is similar but not identical to the native python containers. Specifically, the Indigo containers:
- must contain values that are of types: bool, float, int, string, list or dict. Any list/dict containers must recursively contain only compatible values.
- do not support value access via slicing (we might add this eventually).
- always retrieve values (ex: myprops["key"] or mylist[2]) as a copy and not reference of the object.
- keys can only contain letters, numbers, and other ASCII characters.
- keys cannot contain spaces.
- keys cannot start with a number or punctuation character.
- keys cannot start with the letters XML, xml, or Xml.
The third point above can lead to some unexpected behaviors when compared to python dicts and lists, especially when multiple levels of container nesting is being used. What is means is that you can set items and append to items, but the items returned from the get / iterators are always new copies of the values and not references. For example, consider:
- Code: Select all
c = indigo.List()
c.append(4)
c.append(5)
c.append(True)
c.append(False)
a = indigo.Dict()
a['a'] = "the letter a"
a['b'] = False
a['c'] = c # a COPY of list C above is inserted (not a reference)
print(str(a))
# Because a['c'] has a COPY of list C this will NOT append to instance a:
c.append(6)
print(str(a)) # no change from previous output!
# And because a['c'] returns a COPY of its value this will also NOT append to instance a:
a['c'].append(6)
print(str(a)) # no change from previous output!
But all is not lost. You can just re-assign the nested object to the root container:
- Code: Select all
# Instead you must re-assign a copy to the container. Since we already
# appended c with 6 above, we just need to reassign it now:
a['c'] = c
print(str(a)) # now has a COPY of the updated object, c
If you just need to override an existing value in a container (and not append to it), then a more efficient solution is to use our helper method setitem_in_item. It avoids creating temporary copies of values.
- Code: Select all
a.setitem_in_item('c', 4, "the number six")
print(str(a))
Likewise, it is most efficient to use getitem_in_item when accessing nested items since it avoids temporary copies of containers. For example, this creates a temporary copy of the c object before accessing index 4:
- Code: Select all
a['c'][4] # works, but is slow because a temporary copy of a['c'] is created
Where this returns the same result but is more efficient:
- Code: Select all
a.getitem_in_item('c', 4) # same result, but fast