Python and me

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.

16 thoughts on “Python and me”

  1. I am not sure what you are saying here, but this works as intended:

    if ‘egg’ in {‘egg’: 42}:

    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.

  2. 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).

  3. 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.

  4. 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…

  5. You can check type in Python using “isinstance” function. I presume you need something like this:

    if isinstance(v, str) and v in x:

  6. 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).

  7. @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.

  8. @Christian, looks nice – thanks! Is there any standard lib that does this? I can’t be alone to have this type of issues.

  9. 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 At prompt:
    from mydict import mydict

    d[‘b’] = 1 # ok
    d[1] = ‘a’ # blargh

    if 2.5 in d: pass # blargh

  10. 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.

Comments are closed.