Python美女[从新手到高手]--阅读"见个面问题 HashMap 储存方法"联想
今伯乐在线 上看到一篇文章。一道面试题看 HashMap 的存储方式。也就是问:
在 HashMap 中存放的一系列键值对,当中键为某个我们自己定义的类型。放入 HashMap 后,我们在外部把某一个 key 的属性进行更改,然后我们再用这个 key 从 HashMap 里取出元素。这时候 HashMap 会返回什么?
怎样面试者直接答“这要看自己定义类型的hash值了”,我想面试官会非常惬意。
联想到python中dict的实现,python中字典一般不存在这个问题,由于key的hash值默认是id值,一个对象的id是固定的。
看例如以下代码:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVlZ3VhbmdoYWlkYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
我们能够通过__hash__改动默认hash值。所以__hash__方法还是要看详细业务逻辑,比方我们业务任务name值一样就是同一个对象,看例如以下代码:
class B:
def __init__(self,name):
self.name=name
def __hash__(self):
return hash(self.name)
d={}
b1=B('skycrab')
b2=B('skycrab1')
d[b1]=1
d[b2]=2
b2.name='skycrab'
d[b2]=3
print d
我信心满满的觉得name为‘skycrab‘的值会被更新为3,可事实例如以下:
{<__main__.B instance at 0x02543210>: 2, <__main__.B instance at 0x02543210>: 3, <__main__.B instance at 0x025436C0>: 1}
这让我百思不得其解,hash值明明一样,为什么会觉得是不同对象。导致添加了一个。突然灵光一闪。难道key也须要做比較?打开python源代码我们看看lookdict函数,
当更新字典时会去寻找合适的hashtable位置。调用的就是lookdict函数。
static dictentry *
lookdict(dictobject *mp, PyObject *key, register long hash)
{
register size_t i;
register size_t perturb;
register dictentry *freeslot;
register size_t mask = (size_t)mp->ma_mask;
dictentry *ep0 = mp->ma_table;
register dictentry *ep;
register int cmp;
PyObject *startkey; i = (size_t)hash & mask;
ep = &ep0[i];
if (ep->me_key == NULL || ep->me_key == key)
return ep; if (ep->me_key == dummy)
freeslot = ep;
else {
if (ep->me_hash == hash) {
startkey = ep->me_key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); //比較key的值
if (cmp < 0)
return NULL;
if (ep0 == mp->ma_table && ep->me_key == startkey) {
if (cmp > 0) //仅仅有key相等才会返回已有的位置,否则会寻找一个新的位置
return ep;
}
else {
/* The compare did major nasty stuff to the
* dict: start over.
* XXX A clever adversary could prevent this
* XXX from terminating.
*/
return lookdict(mp, key, hash);
}
}
freeslot = NULL;
}
上面是lookdict的部分源代码(最后没有大括号),如上代码凝视,原来仅仅有hash值一样且key值相等才有更新。那么这就好办了,定义__eq__方法就可以:
class B:
def __init__(self,name):
self.name=name
def __hash__(self):
return hash(self.name)
def __eq__(self,r):
if self.name == r.name:
return True
else:
return False
d={}
b1=B('skycrab')
b2=B('skycrab1')
d[b1]=1
d[b2]=2
b2.name='skycrab'
d[b2]=3
print d
这下结果最终符合期望了,{<__main__.B instance at 0x025F2620>: 2, <__main__.B instance at 0x025F25F8>: 3}
这里我们扩展一下,python中的dict默认採用hash_map的存储结构,所以查找效率非常高。但hash_map的查找效率不稳定。
hash_map的时间复杂度在O(1)-O(N),而基于树结构的map时间复杂度O(logN),比較稳定。
所以在C++中使用hash_map还是map是有考究的。详细能够看看【C++对话系列-产生真正的hash对象】一个。
版权声明:本文博主原创文章,博客,未经同意不得转载。
Python美女[从新手到高手]--阅读"见个面问题 HashMap 储存方法"联想的更多相关文章
- 从新手到高手c++全方位学习 pdf + 视频教程 共18章
淘宝已经和谐了这个网站,原网址:https://item.taobao.com/item.htm?spm=a1z09.8149145.0.0.mb00D0&id=17350311256& ...
- 【JS新手教程】JS获取当前星期几的几种方法
该文通过获取星期几的几种方法,介绍JS里的数组,判断,和字符串截取,可以当作新手教程看,小白也看的懂.获取星期几,可通过Date()对象的getDay()获取,获取的是一个数字,对应的是0,1,2,3 ...
- python从入门到大神---1、初始化实例、类属性、方法
python从入门到大神---1.初始化实例.类属性.方法 一.总结 一句话总结: 方法不加括号是代码段:感觉python方法和js,php很类似,不加括号是代码段,加括号变成方法,比如f,f() 1 ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- [Python]同是新手的我,分享一些经验
本来想分享一些知识,但是发现,写着写着,感觉分享一些经验,或许会少让大家走一些弯路,索性就把标题一改. 我不是教给大家些什么,我没有资格,我也是摸着石头过河,我只是本着分享的精神,在这里分享自己的东西 ...
- python脚本初探---新手如何直接编写一个hello world模块即可执行的.py文件
废话不多说,就讲一下这个背景吧: 事情是这个样子的~ 本着好学的精神,咱就买了本书,学习python结果呢,发现python的教程都是一个样子滴,上来的第一个hello world 都是通过IDLE来 ...
- python线程同步原语--源码阅读
前面两篇文章,写了python线程同步原语的基本应用.下面这篇文章主要是通过阅读源码来了解这几个类的内部原理和是怎么协同一起工作来实现python多线程的. 相关文章链接:python同步原语--线程 ...
- django中url,静态文件,POST请求的配置 分类: Python 2015-06-01 17:00 789人阅读 评论(0) 收藏
平时使用的是pycharm,所以这篇文章主要也是使用pycharm默认创建的django项目为基础进行讲解.项目目录如下图: 1.URL的配置 当创建好项目后,运行项目就可以看到django默认的页面 ...
- requests爬取百度贴吧:python 美女 3
import requests import sys class Tieba(object): def __init__(self, tieba_name, pn): self.tieba_name ...
随机推荐
- Chrome 控制台不完全指南(转)
Chrome的开发者工具已经强大到没朋友的地步了,特别是其功能丰富界面友好的console,使用得当可以有如下功效: 更高「逼格」更快「开发调试」更强「进阶级的Frontender」 Bug无处遁形「 ...
- 【原版的】Redis事件驱动内核
Redis事件驱动内核 作者:cf (360电商技术组) 概述 Redis实现了自己的事件驱动,与开源事件库libevent.libev一样,都是基于I/O多路复用技术实现的.出于性能和代码精炼双方面 ...
- TextWatcher原因activity内存泄漏问题
TextWatcher原因activity内存泄漏. EditText配置addTextChangedListener该接口,至onDestroy电话里removeTextChangedListene ...
- HDU ACM 1065 I Think I Need a Houseboat
分析:告诉协调的房子,每年(0,0)作为一个半圆区域的中心将被添加50.请教如何多年以来,这家的位置将是半圆内.注意pi必须采取3.1415926管辖权. #include<iostream&g ...
- Linux网络基础设施配置
1.TCP/IP网络配置文件 /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network /etc/host.conf /etc/ ...
- spring 整合quartz的方式——简单介绍
一.继承QuartzJobBean,重写executeInternal方法 <bean name="statQuartzJob" class="org.spring ...
- hdu 5045 费用流
滚动建图,最大费用流(每次仅仅有就10个点的二分图).复杂度,m/n*(n^2)(n<=10),今年网络赛唯一网络流题,被队友状压DP秒了....难道网络流要逐渐退出历史舞台???.... #i ...
- “NET网络”进行中,多管齐下的人才力挫“”粗俗
随着互联网的迅猛发展,一些不太干净.低俗的甚至色情的内容不断浮现.不仅严重影响了我们的上网体验,也成为扰乱互联网正常秩序的罪魁祸首,部分不法内容甚至给网民造成了一定的財产损失.在这样的 ...
- myeclipse egit 安装失败 org.eclipse.e4.ui.css.swt.theme 0.0.0
[前言] 首先确保您可能会被安装在阅读本文之前,myeclipse egit, 见文章:http://blog.csdn.net/uikoo9/article/details/17247405 事实上 ...
- eclipse 在win7 64两个图标出现位操作系统无法锁定到任务栏或任务栏
eclipse 在win7 64位操作系统无法锁定到任务栏或者任务栏上出现两个图标 解决的方法 eclipse在win7 64bit下无法锁定到任务栏问题(或是锁定后任务栏出现两个eclipse图标) ...