Commits

briancurtin  committed 8123079

Add dictionary porting section.
Explains dict views, removal of iter* methods, and removal of the
has_key method.

  • Participants
  • Parent commits 89e3f67

Comments (0)

Files changed (1)

File manuals/python3_porting/py-porting.rst

                 return self.value
 
 
+Dictionaries
+============
+
+A number of changes were made to the :class:`dict` type to better integrate it
+with the current trends in the language. :pep:`3106`, which was adopted in 3.0,
+outlines the introduction of a new feature called dictionary views, or a more
+lightweight replacement for the lists returned by several methods.
+Additionally, the PEP explains the removal of ``iter*`` methods on
+the attributes of dictionaries. Another removal is the :meth:`dict.has_key`
+method.
+
+
+Supporting Dictionary Views
+---------------------------
+
+Python 3.0 introduced the concept of views, or a dynamic peek into the
+contents of a :class:`dict`. Even when a dictionary is mutated, all of its
+views are kept in-sync to reflect the current state of the dictionary.
+Views are supported on :meth:`dict.items`, :meth:`dict.keys`,
+and :meth:`dict.values` to replace the old-style form which returned a
+:class:`list`.
+
+.. admonition:: Backporting Note
+
+   Since the view concept has no equivalent in 2.x, the backporting of views
+   was done in Python 2.7 under different names. View-returning methods are
+   prefixed with ``view``, while the list-returning methods remain unchanged.
+
+
+Supporting 2.7 and 3.x
+^^^^^^^^^^^^^^^^^^^^^^
+
+Due to the name difference in the APIs, supporting views in both 2.7 and 3.x
+results in a less than beautiful snipped of code.
+::
+
+    import sys
+
+    view_attr = "items" if sys.version_info.major == 3 else "viewitems"
+    location = {"city" : "Chicago", "state" : "Illinois"}
+
+    def view_location():
+        for key, value in getattr(d, view_attr)():
+            print("{}: {}".format(key, value))
+
+::
+
+    >>> view_location()
+    city: Chicago
+    state: Illinois
+
+
+Supporting pre-2.7 and 3.x
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If your project supports versions prior to 2.7 where there is no concept
+of a view, you can create a list from a view in order to safely remain
+compatible across versions.
+::
+
+    keys = list(location.keys())
+
+
+Without a list, you should be aware of how views function when the dictionary
+is changed. In a lot of cases you will be fine as-is. Other cases may require
+an explicit list like above.
+::
+
+    Python 2.6.5+ (release26-maint:83007:83008, Jul 27 2010, 22:52:5)
+    [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> location = {"city" : "Chicago", "state" : "Illinois"}
+    >>> keys = location.keys()
+    >>> print(keys)
+    ['city', 'state']
+    >>> del location["city"]
+    >>> print(keys)
+    ['city', 'state']
+
+::
+
+    Python 3.2a0 (py3k:83172M, Jul 27 2010, 23:01:10)
+    [GCC 4.0.1 (Apple Inc. build 5465)] on darwin
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> location = {"city" : "Chicago", "state" : "Illinois"}
+    >>> keys = location.keys()
+    >>> print(keys)
+    dict_keys(['city', 'state'])
+    >>> del location["city"]
+    >>> print(keys)
+    dict_keys(['state'])
+
+Notice that the 3.2 code is using a view for :meth:`dict.keys <3x:dict.keys>`,
+which results in the ``keys`` object being updated after the dictionary was
+modified. Contrast that with the 2.6 example which uses a :class:`list` for
+``keys``, which does not stay in-sync with the dictionary from which the
+keys are from.
+
+
+Replacing ``iter*`` methods
+---------------------------
+
+Use of :meth:`dict.iteritems` and :meth:`dict.itervalues` should be replaced
+by the following familiar looping construct.
+::
+
+    for key, value in d.items()
+
+The same could be done for :meth:`dict.iterkeys`; however, ``key in d`` is a
+more common option.
+
+
+Replacing :meth:`dict.has_key`
+------------------------------
+
+The :meth:`dict.has_key` is not supported in Python 3.0, in favor of the
+``key in d`` idiom which was introduced in 2.2. Formal deprecation of
+:meth:`dict.has_key` began in 2.6.
+
++--------------------------+--------------------+
+| Python 2 format          | Python 3 format    |
++==========================+====================+
+|::                        |::                  |
+|                          |                    |
+|    if d.has_key("foo"):  |    if "foo" in d:  |
+|        bar()             |        bar()       |
++--------------------------+--------------------+
+
+
 Strategies
 ==========