I like Python, but I’d love it if it had support for types – even if one of them was a generic duck-typed object or variant.
x = {}
k = "potential key"
v = MyValue() # Clearly not a key
if v in x:
pass # Always fails silently
I apparently live and learn.
Update! Apparently I’m stupid while summarizing the error (always copy, never recall). I did not use k in the if statement, rather, I used v which is not a key. This is a programmer error. However, Python does not tell me so, it just does what it asks it to do, i.e. tell me if the not-a-key is a key.
Thanks to Ralk for pointing this out.
I am not sure what you are saying here, but this works as intended:
if ‘egg’ in {‘egg’: 42}:
print(“Yes!”)
Generally, I think “k in x” is equivalent to “k in x.keys()” when x is a dict. I was unable to find a case where they differ.
Then its probably me being stupid… Let me see if I can setup an example that does work from my larger code base (and thanks for poking at this).
Looked back at the code. Turns out that I broke (or rather, fixed) the example when clearing it up…
Darn, Ralf beat me to it
About Ralf comment, the main difference is that in python 2, k in dictionary is O(1) while k in dictionary.keys() is O(n), in python 3 dictionary.keys() returns a dict_keys object that behaves as expected.
About if v in k, if v is not hasheable you’ll get a TypeError.
Ralf is quick :-)
The point is that when doing the obvious mistake of using the wrong key type (which still is hashable) you don’t get an error, you get no result. Since I expect there to be a case where “no key in dict” is valid, the program just keeps running. I’d love if I could hint to the dict what a key is and get a TypeError even when the (wrong) key is hasheable…
You can check type in Python using “isinstance” function. I presume you need something like this:
if isinstance(v, str) and v in x:
pass
Nice, but I guess that I want to do that when declaring the dict. A bit like QHash(). Since Python consists (a large) part of magic, I guess this is possible. But some generic type-hinting syntax would be nice. That is, I like this PEP: https://www.python.org/dev/peps/pep-0484/ .
Python can’t tell you that v is not a key, as it *can* be a key. Almost anything (that allows comparison) can be a key *in the same* dict. Why do you say v is not a key? What does MyValue() return?
E.g. this is valid x = {‘abc’:1, 1:’abc’, (lambda x : x+1):’func!’}. Of course, it is useless (for most usages) to do this, as ‘func!’ is not reacheable by key anymore (but it is still reacheable by iteration).
@Christian, yes I know. That is the problem. I have no way to inform Python what a key is, so that it can help me by realizing that v is not a key.
Well, it can be done by overloading built-in dict’s __setitem__ to only accept keys of a type of your choice. A hint here: http://stackoverflow.com/questions/817884/creating-dictionaries-with-pre-defined-keys
And then using e.g.
if type(v) == type(x.keys()[0]) and v in x:
It’s much boilerplate but then the right language for what you want to do is C++, not Python ;-)
Ah, you can also override __contains__.
@Christian, looks nice – thanks! Is there any standard lib that does this? I can’t be alone to have this type of issues.
No standard that I know. But:
# todo write proper exception
class SomeProperException: pass
class mydict(dict):
def __init__(self, keytype):
self.keytype = type(keytype)
def __setitem__(self, k, v):
if not type(k) == self.keytype:
raise SomeProperException
dict.__setitem__(self, k, v)
def __contains__(self, k):
if not type(k) == self.keytype:
raise SomeProperException
return dict.__contains__(self,k)
Save this as mydict.py. At prompt:
from mydict import mydict
d=mydict(‘a’)
d[‘b’] = 1 # ok
d[1] = ‘a’ # blargh
if 2.5 in d: pass # blargh
Oh… it ate all the alignments…
WordPress likes spaces – it eats them as soon as it gets a chance. Thanks for the source, I’ll try incorporating it over the weekend.