0

I created a function that counts the number of times a string has appeared in a list and returns a dictionary. I got the program to work, but interestingly enough, when I changed the value of a key value, d[i], the order of the names changed . Why is python doing this?

Before:

def countlist(l):
    d = {}
    for i in l:
        if i not in d:
            d[i] = 0
        else:
            d[i] += 1
    return d

input:

countlist(['helen','andrew','chris','chris','helen'])

result:

{'helen': 1, 'andrew': 0, 'chris': 1}

After:

def countlist(l):
    d = {}
    for i in l:
        if i not in d:
            d[i] = 1
        else:
            d[i] += 1
    return d

input: countlist(['helen','andrew','chris','chris','helen'])

result: {'andrew': 1, 'chris': 2, 'helen': 2}

abhi1610
  • 721
  • 13
  • 28
I Like
  • 1,711
  • 2
  • 27
  • 52

1 Answers1

1

Did you execute this code in different sessions of Python? If so, the hash code for the string keys likely changed. To defend against denial of service attacks caused by intentionally submitting keys with colliding hashes, Python salts hashes for str, bytes and other "strings of data" types.

Per the docs:

Note

By default, the __hash__() values of str, bytes and datetime objects are “salted” with an unpredictable random value. Although they remain constant within an individual Python process, they are not predictable between repeated invocations of Python.

This is intended to provide protection against a denial-of-service caused by carefully-chosen inputs that exploit the worst case performance of a dict insertion, O(n^2) complexity. See http://www.ocert.org/advisories/ocert-2011-003.html for details.

Changing hash values affects the iteration order of dicts, sets and other mappings. Python has never made guarantees about this ordering (and it typically varies between 32-bit and 64-bit builds).

See also PYTHONHASHSEED.

If you require repeatable ordering based on insertion order, use collections.OrderedDict.

Community
  • 1
  • 1
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271