Re: [Tutor] Behavior of dictionary in mapping keys that evaluate equal

2016-05-12 Thread khalil zakaria Zemmoura
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

2016-05-11 Thread Peter Otten
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

2016-05-11 Thread Steven D'Aprano
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

2016-05-11 Thread cs

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


[Tutor] Behavior of dictionary in mapping keys that evaluate equal

2016-05-11 Thread khalil zakaria Zemmoura
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.

Am I missing something?

If that's what happen, why when running Dic.items() it return [(True,
'No')] instead of [(1, 'No')]
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor