V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fanqieipnet
V2EX  ›  推广

由于哈希冲突,不同值的对象也可能具有相同的哈希值

  •  
  •   fanqieipnet · 2020-12-29 16:38:20 +08:00 · 775 次点击
    这是一个创建于 1220 天前的主题,其中的信息可能已经有所发展或是发生改变。
    由于哈希冲突,不同值的对象也可能具有相同的哈希值。这是为什么呢?今天番茄加速就来分析一下。

      字符串驻留

       In [1]: a = 'something'

      ...: b = 'some'+'thing'

      ...: id(a)==id(b)

       Out[1]: True

      如果上面例子返回 True,但是下面例子为什么是 False:

       In [1]: a = '@zglg.com'

       In [2]: b = '@zglg'+'.com'

       In [3]: id(a)==id(b)

       Out[3]: False

      这与 Cpython 编译优化相关,行为称为字符串驻留,但驻留的字符串中只包含字母,数字或下划线。

      相同值的不可变对象

       In [5]: d = {}

      ...: d[1] = 'java'

      ...: d[1.0] = 'python'

       In [6]: d

       Out[6]: {1: 'python'}

      ### key=1,value=java 的键值对神器消失了

       In [7]: d[1]

       Out[7]: 'python'

       In [8]: d[1.0]

       Out[8]: 'python'

      这是因为具有相同值的不可变对象在 Python 中始终具有相同的哈希值

      由于存在哈希冲突,不同值的对象也可能具有相同的哈希值。

      对象销毁顺序

      创建一个类 SE:

       class SE(object):

       def __init__(self):

       print('init')

       def __del__(self):

       print('del')

      创建两个 SE 实例,使用 is 判断:

       In [63]: SE() is SE()

       init

       init

       del

       del

       Out[63]: False

      创建两个 SE 实例,使用 id 判断:

       In [64]: id(SE()) == id(SE())

       init

       del

       init

       del

       Out[64]: True

      调用 id 函数, Python 创建一个 SE 类的实例,并使用 id 函数获得内存地址后,销毁内存丢弃这个对象。

      当连续两次进行此操作, Python 会将相同的内存地址分配给第二个对象,所以两个对象的 id 值是相同的.

      但是 is 行为却与之不同,通过打印顺序就可以看到。

      充分认识 for

       In [65]: for i in range(5):

      ...: print(i)

      ...: i = 10

       0

       1

       2

       3

       4

      为什么不是执行一次就退出?

      按照 for 在 Python 中的工作方式, i = 10 并不会影响循环。range(5)生成的下一个元素就被解包,并赋值给目标列表的变量 i.

      认识执行时机

       array = [1, 3, 5]

       g = (x for x in array if array.count(x) > 0)

       g 为生成器,list(g)后返回[1,3,5],因为每个元素肯定至少都出现一次。所以这个结果这不足为奇。但是,请看下例:

       array = [1, 3, 5]

       g = (x for x in array if array.count(x) > 0)

       array = [5, 7, 9]

      请问,list(g)等于多少?这不是和上面那个例子结果一样吗,结果也是[1,3,5],但是:

       In [74]: list(g)

       Out[74]: [5]

      这有些不可思议~~ 原因在于:

      生成器表达式中, in 子句在声明时执行, 而条件子句则是在运行时执行。

      所以代码:

       array = [1, 3, 5]

       g = (x for x in array if array.count(x) > 0)

       array = [5, 7, 9]

      等价于:

       g = (x for x in [1,3,5] if [5,7,9].count(x) > 0)

      看明白了吗?
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1094 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 17:51 · PVG 01:51 · LAX 10:51 · JFK 13:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.