Re: [Tutor] Behavior of dictionary in mapping keys that evaluate equal
Steven D'Aprano wrote: > On Wed, May 11, 2016 at 02:00:47PM +0100, khalil zakaria Zemmoura wrote: >> Hi, >> >> Suppose we have a dict >> Dic = { True: 'yes', 1: 'No'} >> >> According to the Python 3 documentation, the keys must have a unique >> value so True is converted to integer because of the type coercion >> (boolean are subtype of integer) so boolean are winded to integer to be >> compared. > > No, not quite. Keys aren't converted to anything. The above is > equivalent to: > > Dic = {} > Dic[True] = 'yes' > Dic[1] = 'no' > > That part is straight-forward. But remember that True == 1: > > py> True == 1 > True > > and they have the same hash: > > py> hash(True), hash(1) > (1, 1) > > so as far as Python is concerned, they are the same key. The same > applies to the float 1.0: > > py> d = {True: 'yes'} > py> d[1] > 'yes' > py> d[1.0] > 'yes' > > > One last fact to remember: if the key is already found in the dict, it > isn't replaced. So: > > py> d = {1: 'no'} > py> d[True] = 'yes' > py> d > {1: 'yes'} > > > Does this now explain why > > {True: 'yes', 1: 'no'} > > returns {True: 'no'}? As Steven says, there is no conversion. The mechanism is completely general: The first of a sequence of equal keys wins. Here is an example with a custom class: >>> class Key: ... def __eq__(self, other): ... return other == 1 ... def __hash__(self): ... return 1 ... def __repr__(self): ... return "" ... >>> int(Key()) Traceback (most recent call last): File "", line 1, in TypeError: int() argument must be a string, a bytes-like object or a number, not 'Key' Even though there is no way to convert a Key to int the dict literals behave as with bool and int: >>> d = {1: "a", Key(): "b"} >>> d {1: 'b'} >>> d = {Key(): "a", 1: "b"} >>> d {: 'b'} Thanks a lot, what I was missing is the behavior of dict constructor, so that's gives me more understanding. Regards ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Behavior of dictionary in mapping keys that evaluate equal
Steven D'Aprano wrote: > On Wed, May 11, 2016 at 02:00:47PM +0100, khalil zakaria Zemmoura wrote: >> Hi, >> >> Suppose we have a dict >> Dic = { True: 'yes', 1: 'No'} >> >> According to the Python 3 documentation, the keys must have a unique >> value so True is converted to integer because of the type coercion >> (boolean are subtype of integer) so boolean are winded to integer to be >> compared. > > No, not quite. Keys aren't converted to anything. The above is > equivalent to: > > Dic = {} > Dic[True] = 'yes' > Dic[1] = 'no' > > That part is straight-forward. But remember that True == 1: > > py> True == 1 > True > > and they have the same hash: > > py> hash(True), hash(1) > (1, 1) > > so as far as Python is concerned, they are the same key. The same > applies to the float 1.0: > > py> d = {True: 'yes'} > py> d[1] > 'yes' > py> d[1.0] > 'yes' > > > One last fact to remember: if the key is already found in the dict, it > isn't replaced. So: > > py> d = {1: 'no'} > py> d[True] = 'yes' > py> d > {1: 'yes'} > > > Does this now explain why > > {True: 'yes', 1: 'no'} > > returns {True: 'no'}? As Steven says, there is no conversion. The mechanism is completely general: The first of a sequence of equal keys wins. Here is an example with a custom class: >>> class Key: ... def __eq__(self, other): ... return other == 1 ... def __hash__(self): ... return 1 ... def __repr__(self): ... return "" ... >>> int(Key()) Traceback (most recent call last): File "", line 1, in TypeError: int() argument must be a string, a bytes-like object or a number, not 'Key' Even though there is no way to convert a Key to int the dict literals behave as with bool and int: >>> d = {1: "a", Key(): "b"} >>> d {1: 'b'} >>> d = {Key(): "a", 1: "b"} >>> d {: 'b'} ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Behavior of dictionary in mapping keys that evaluate equal
On Wed, May 11, 2016 at 02:00:47PM +0100, khalil zakaria Zemmoura wrote: > Hi, > > Suppose we have a dict > Dic = { True: 'yes', 1: 'No'} > > According to the Python 3 documentation, the keys must have a unique value > so True is converted to integer because of the type coercion (boolean are > subtype of integer) so boolean are winded to integer to be compared. No, not quite. Keys aren't converted to anything. The above is equivalent to: Dic = {} Dic[True] = 'yes' Dic[1] = 'no' That part is straight-forward. But remember that True == 1: py> True == 1 True and they have the same hash: py> hash(True), hash(1) (1, 1) so as far as Python is concerned, they are the same key. The same applies to the float 1.0: py> d = {True: 'yes'} py> d[1] 'yes' py> d[1.0] 'yes' One last fact to remember: if the key is already found in the dict, it isn't replaced. So: py> d = {1: 'no'} py> d[True] = 'yes' py> d {1: 'yes'} Does this now explain why {True: 'yes', 1: 'no'} returns {True: 'no'}? -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Behavior of dictionary in mapping keys that evaluate equal
On 11May2016 14:00, khalil zakaria Zemmoura wrote: Suppose we have a dict Dic = { True: 'yes', 1: 'No'} According to the Python 3 documentation, the keys must have a unique value so True is converted to integer because of the type coercion (boolean are subtype of integer) so boolean are winded to integer to be compared. As it happens. The core lesson here is that usually you want all your dictionary keys to be the same type. If that's what happen, why when running Dic.items() it return [(True, 'No')] instead of [(1, 'No')] Because the dictionary is assembled sequentially (probably an implementation detail, though since Python expressions are evaluated left to right it might possibly be guarrenteed). So: First 'yes' is loaded into the dict with the key True. The 'No' is loaded, using key 1. This finds the same slot as True, and puts 'No' there. Without changing the key value. So true now has 'No' stored with it. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor