Pythonic dictionary polling method - using the key value when it exists

I have a working solution for this issue, it is just not very pyphonic. I work in Python 2.7 and therefore cannot use Python 3 solutions.

I have a dictionary that is regularly updated. In the end, the key, let it be called "foo", with the value appears in the dictionary. I want to continue polling this object and get this dictionary until the "foo" key appears, after which I want to get the value associated with this key and use it.

Here is some psuedo code that works right now:

polled_dict = my_object.get_dict()
while('foo' not in polled_dict.keys()):
    polled_dict = my_object.get_dict()
fooValue = polled_dict['foo']

Let me emphasize that the code is working now. It feels rude, but it works. The potential involution that I came up with is the following:

fooValue = None
While fooValue is None:
    polled_dict = my_object.get_dict()
    fooValue = polled_dict.get('foo')

, . polled_dict.get('foo') , dict ( while while), . , , , .

, , , ( - ), pythonic. , . - ? , , ?

EDIT. , . , , , , , :

" API, . . ( , ). , , , dict , - . - (, API , , , -, / API, , , .)"

+4
6

- dict.

, - :

class NoisyDict(dict):
    def __init__(self, *args, **kwargs):
        self.handlers = {}
        #Python 3 style
        super().__init__(*args, **kwargs)

    def add_handler(self, key, callback):
        self.handlers[key] = self.handlers.get(key, [])
        self.handlers[key].append(callback)

    def __getitem__(self, key):
        for handler in self.handlers.get(key, []):
            handler('get', key, super().__getitem__(key))
        return super().__getitem__(key)

    def __setitem__(self, key, value):
        for handler in self.handlers.get(key, []):
            handler('set', key, value)
        return super().__setitem(value)

d = NoisyDict()

d.add_handler('spam', print)

d['bar'] = 3
d['spam'] = 'spam spam spam'
+1

, . -. , , , :

polled_dict = my_object.get_dict()
while 'foo' not in polled_dict:
    pass # optionally sleep
fooValue = polled_dict['foo']

- pipe/socket/thread-lock - .

+1

:

from itertools import repeat
gen_dict = (o.get_dict() for o in repeat(my_object))
foo_value = next(d['foo'] for d in gen_dict if 'foo' in d)
+1

- ? (, ). , . , ; MyDict (watcher = MyWatcher(), a = 1, b = 2) - a b . , .

class Watcher(object):
    """Watches entries added to a MyDict (dictionary).  key_found() is called
    when an item is added whose key matches one of elements in keys.
    """
    def __init__(self, *keys):
        self.keys = keys

    def key_found(self, key, value):
        print key, value


class MyDict(dict):

    def __init__(self, *args, **kwargs):
        self.watcher = kwargs.pop('watcher')
        super(MyDict, self).__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        super(MyDict, self).__setitem__(key, value)
        if key in self.watcher.keys:
              self.watcher.key_found(key, value)


watcher = Watcher('k1', 'k2', 'k3')
d = MyDict(watcher=watcher)
d['a'] = 1
d['b'] = 2
d['k1'] = 'k1 value'
+1

, Try/Except "Pythonic"?

while .

polled_dict = my_object.get_dict()
while True:
    time.sleep(0.1)
    try: 
        fooValue = polled_dict['foo']
        return (foovalue) # ...or break
    except KeyError:
        polled_dict = my_object.get_dict()
+1

, defaultdict .

from collections import defaultdict

mydeafultdict = defaultdict(lambda : None)
r = None

while r is None:
    r = mydeafultdict['foo']

a defaultdictworks just like a regular dictionary, except when the key does not exist, it calls the function provided to it in the constructor to return the value. In this case, I gave him a lambda that just returns None. In this case, you can continue to receive foo, when there is a value associated with it, it will be returned.

0
source

Source: https://habr.com/ru/post/1543905/


All Articles