dictionary/hash and '1' versus 1

  • Thread starter Reedick, Andrew
  • Start date
R

Reedick, Andrew

As a Perl monkey in the process of learning Python, I just stepped on
the "'1' (string) is not the same as 1 (integer) in regards to keys for
dictionaries/hashes" landmine. Is there a good way to ensure that
numbers represented as strings or ints do not get mixed up as keys?

Example of the problem:
>>> h2 = { 1 : ''}
>>> print h2.has_key(1)
True
>>> print h2.has_key('1')
False

The problem occurred because a method used to generate keys was
returning a string instead of a number without an explicit conversion
taking place. And since I was using hash.get(i, default_value) to avoid
having to pair every key lookup with a hash.has_key(), no exception was
thrown when the key wasn't found.

It's fugly to wrap every key reference in str(), ex:
foo[str(some_func(i))]. It's tedious to add a has_key before every key
lookup. And I have no real desire to stuff every hash inside a class in
order to ensure that keys are converted to strings.

Any good solutions or accepted practices to prevent the intermixing of
number strings and integers as hash keys? A hash wrapper class seems to
be the best bet so far.



*****

The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential, proprietary, and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers. GA623
 
J

John Machin

As a Perl monkey in the process of learning Python, I just stepped on
the "'1' (string) is not the same as 1 (integer) in regards to keys for
dictionaries/hashes" landmine.

Congratulations. You have just stepped off the "'1' (string) is the
same as 1 (integer) in regards to several purposes" landmine.

Welcome to the awk-free world :)
Is there a good way to ensure that
numbers represented as strings or ints do not get mixed up as keys?

Example of the problem:
False

The problem occurred because a method used to generate keys was
returning a string instead of a number without an explicit conversion
taking place. And since I was using hash.get(i, default_value) to avoid
having to pair every key lookup with a hash.has_key(), no exception was
thrown when the key wasn't found.

has_key is a has_been ... use "key in dict" instead of
"dict.has_key(key)"
It's fugly to wrap every key reference in str(), ex:
foo[str(some_func(i))].

Fugliness is in the eye of the beholder.
 
S

Steven D'Aprano

The problem occurred because a method used to generate keys was
returning a string instead of a number without an explicit conversion
taking place. And since I was using hash.get(i, default_value) to avoid
having to pair every key lookup with a hash.has_key(), no exception was
thrown when the key wasn't found.


# How to fix this broken function without modifying the source?
def foo(arg):
"""Returns a string instead of a number."""
return "1" # oops I meant 1



_foo = foo # save a reference to original broken function
foo = lambda *args, **kwargs: int(_foo(*args, **kwargs)) # and patch it


And now you can use foo(arg) confident that it will always return an int
like you expect.

Modifications of this technique should be obvious.
 
E

Erik Max Francis

As a Perl monkey in the process of learning Python, I just stepped on
the "'1' (string) is not the same as 1 (integer) in regards to keys for
dictionaries/hashes" landmine.

This isn't a landmine; this is a _good_ thing. Python is strongly typed.
Is there a good way to ensure that
numbers represented as strings or ints do not get mixed up as keys?

Convert them all to either strings or integers (whichever is more
useful) before you add them to the dictionary, really.
It's fugly to wrap every key reference in str(), ex:
foo[str(some_func(i))].

Then wrap it in a function or a method of one of your classes. You only
need to write it once.
It's tedious to add a has_key before every key
lookup.

There's no need to do this, though you don't say why you're bothering
to. Either use .setdefault, or just query and get the exception, or
just insert the new key, value pair to override the contents.
Any good solutions or accepted practices to prevent the intermixing of
number strings and integers as hash keys? A hash wrapper class seems to
be the best bet so far.

If you want to make sure something is always done in a particular
situation, then solution is to have a function or method that does that,
and then just call that function or method. That's true in any language
-- any one that has functions, anyway.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top