Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Dictionary - Modify __getitem__?

Ok so i've build my own variable handler which has a __getitem__ function for use when accessing data via data[key], it works great except for when trying to access a link of items:

data["key"]["subkey"]


def __getitem__(self, key, **args):
    print key
    ...
    return self.dict[key]

When trying to access a subkey that doesn't exist, Python simply returns a KeyError without printing "subkey", why is this and how can I get Python to print out what I'm actually trying to get?

I know that I've probably misunderstood the mechanics but is there a way to emulate a dictionary AND follow the string of data that's being requested? Mainly so I can dynamically log the missing variables in a dictionary flow...

This obviously works (but it's not the native syntax that I like):

data["key:subkey"]

def __getitem__(self, key, **args):
    for slice in key.split(':'):
        print key
    ...

The goal is to emulate the following,

Works:

data = {'key' : {'subkey' : 1}}
print data["key"]["subkey"]

Will not work, but I want to catch the exception within __getitem__ and then create the missing key automatically or just log the missing subkey:

data = {'key' : {}}
print data["key"]["subkey"]

Solution:

class Var():
    def __init__(self):
        self.dict = {'test' : {}}
    def __getitem__(self, var, **args):
        print ':',var
        if var in self.dict:
            v = Var(self.dict[var])
            return v

print vHandle['test']['down']

Output:

: test

: down

None

like image 521
Torxed Avatar asked Oct 29 '25 03:10

Torxed


2 Answers

The fact is that when Python encounters an expression such as data["key"]["subkey"], what is done internally is (data["key"])["subkey"]. That is, the first part of the expression is resolved: the retrievalof the item "key" from the object "data". Then, Python tries do call __getitem__ on the resulting object of that expression. If such resulting object does not have a __getitem__method itself, there is your error.

There are two possible workarounds there: you should either work with "tuple indexes" - like data["key", "subkey"](and then test on your __getitem__ method wether you got a tuple instance as the key) - or make __getitem__ return an specialized object that also features a __getitem__ method - even if all it does is to log the requested keys.

like image 153
jsbueno Avatar answered Oct 31 '25 18:10

jsbueno


Remember: tmp = foo['bar']['baz'] is the same as tmp = foo['bar']; tmp = tmp['baz']

So to allow arbitrary depths your __getitem__ method must return a new object that also contains such a __getitem__ method.

like image 31
ThiefMaster Avatar answered Oct 31 '25 18:10

ThiefMaster



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!