python dictionary conundrum

2024/10/10 14:31:53

On the console I typed in

>>> class S(str): pass
...
>>> a = 'hello'
>>> b = S('hello')
>>> d = {a:a, b:b}
>>> d
{'hello': 'hello'}
>>> type(d[a])
<class '__main__.S'>
>>> type(d[b])
<class '__main__.S'>

I thought at first that the reason that d only kept one pair was because hash(a) and hash(b) returned the same values, so I tried:

>>> class A(object):
...     def __hash__(self):
...             return 0
... 
>>> class B(object):
...     def __hash__(self):
...             return 0
... 
>>> d = {A():A(),B():B()}
>>> d
{<__main__.A object at 0x101808b90>: <__main__.A object at 0x101808b10>, <__main__.B object at 0x101808d10>: <__main__.B object at 0x101808cd0>}

Now I'm confused. How come in the first code listing, d only kept one pair, but in the second listing d both keys were kept despite having same hash?

Answer

The two objects in your original example were collapsed not because they have the same hash, but because they compare equal. Dict keys are unique with respect to equality, not hash. Python requires that any two objects that compare equal must have the same hash (but not necessarily the reverse).

In your first example, the two objects are equal, since they both have the str equality behavior. Since the two objects compare equal, they are collapsed to one. In the second example, they don't compare equal. By default user-defined classes use identity for equality --- that is, each object compares equal only to itself. So your two objects are not equal. It doesn't matter than they have the same hash.

https://en.xdnf.cn/q/69830.html

Related Q&A

Celery 4 not auto-discovering tasks

I have a Django 1.11 and Celery 4.1 project, and Ive configured it according to the setup docs. My celery_init.py looks likefrom __future__ import absolute_importimport osfrom celery import Celery# set…

Is it possible to use a custom filter function in pandas?

Can I use my helper function to determine if a shot was a three pointer as a filter function in Pandas? My actual function is much more complex, but i simplified it for this question.def isThree(x, y…

what is request in Django view

In the Django tutorial for the first app in Django we havefrom django.http import HttpResponsedef index(request):return HttpResponse("Hello, world. Youre at the polls index.")And then the url…

Cannot update python package on anaconda to latest version

Some of my python packages on anaconda cannot be updated to the latest version.For instance, beautifulsoup4 latest version on anaconda is v4.71 as seen in the release notes. https://docs.anaconda.com/a…

How does tensorflow.pad work?

There is the example of tensorflow.pad():# t = is [[1, 2, 3], [4, 5, 6]]. # paddings is [[1, 1,], [2, 2]]. # rank of t is 2.tf.pad(t, paddings, "CONSTANT") ==> [[0, 0, 0, 0, 0, 0, 0],[…

Installing PyPotrace on Windows 10

I would like to install Potrace on my Windows 10 Computer and I will be using it with python 2.7.5. I am following the installation instruction from this site.( https://pypi.python.org/pypi/pypotrace) …

dateutil 2.5.0 is the minimum required version

Im running the jupyter notebook (Enthought Canopy python distribution 2.7) on Mac OSX (v 10.13.6). When I try to import pandas (import pandas as pd), I am getting the complaint: ImportError: dateutil …

pytest fixture - get value and avoid error Fixture X called directly

I have updated pytest to 4.3.0 and now I need to rework test code since calling fixtures directly is deprecated. I have an issue with fixtures used in an unittest.TestCase, how do I get the value retur…

Django limit the number of requests per minute

Im trying to limit the number of requests from an IP in case I get too many requests from it. For example: if I will get more than 50 requests per minute I want to block that IP for 5 minutes. When I u…

How to add template variable in the filename of an EmailOperator task? (Airflow)

I cant seem to get this to work.I am trying to send daily a given file, whose name is like file_{{ds_nodash}}.csv.The problem is that I cant seem to add this name as the filename, since it seems it can…