2

I have nested dictionary

default=time.time()
a={"key":{"key_value":"value", "time": default}}

Is it possible that time will change automatically, when I change dictionary?

For example,

a
Out[40]:
{'key': {'key_value': 'value', 'time': 1516968395.7678363}}

When I change key_value:

a["key"]["key_value"]="value2"

It still gives me the same time, but I need updated current time

a
Out[44]:
{'key': {'key_value': 'value2', 'time': 1516968395.7678363}}
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
elenaby
  • 167
  • 2
  • 11
  • you probably have to create a custom class for that – Ma0 Jan 26 '18 at 12:30
  • You could make the value for the key `"time"` a function `mydict = {'time': lambda: default_time}`, but then you'd have to evaluate it every time you accessed it: `mydict['time']()` – pault Jan 26 '18 at 12:53

2 Answers2

1

I think that there are two ways you could go about this. You could subclass dict to make a new class for which each addition or modification appends a modification time, or you could create function to modify an existing dict that also appends a modification time.

Subclassing is probably a more robust method, but I think the later is probably easier / more readable, so having a quick try at that approach:

import time

def nested_dict_updater(dict, top_key, nested_key, value):
    dict[top_key][nested_key] = value
    dict[top_key]['modification_time'] = time.time()

# Original dict
now = time.time()
d = {"top_key": {"nested_key": "value", "modification_time": now}}
print(d)

# Updated dict
nested_dict_updater(d, "top_key", "nested_key", "new_value")
print(d)

# Add another nested key and value
nested_dict_updater(d, "top_key", "another_key", "second_value")
print(d)

This simple function allows you to update any of your nested key's values, or add a new nested key with value, and records the modified time for that top level key.

halfer
  • 19,824
  • 17
  • 99
  • 186
North Laine
  • 384
  • 2
  • 14
0

Expanding on my comment, which is inspired by this answer to a different question (please upvote that one if you like this one):

You can assign the value of the key "time" to be a lambda function.

default=time.time()
a={"key":{"key_value":"value", "time": lambda: default}}

But if you were to print a, you'd see this:

>>> print(a)
{'key': {'key_value': 'value', 'time': <function <lambda> at 0x7f39aa90cc08>}}

So, make a helper function to which will assign the current value of default to the key "time" when you want:

def get_my_dict(a, time_key="time"):
    d = {}
    d = {
        k:(a[k]() if k == time_key else a[k])
         if not isinstance(a[k], dict) 
         else get_my_dict(a[k]) for k in a
    }
    return d

In this case, I am using recursion to go through all nested dictionaries looking for the time_key. If it is found, the function is called (notice the parentheses)- otherwise, the value is returned. You can simplify this based on your needs.

Now you can do the following:

>>> new_a = get_my_dict(a)
>>> print(new_a)
{'key': {'key_value': 'value', 'time': 1516979156.041796}}

If we subsequently update default:

>>> default = 0
>>> new_a = get_my_dict(a)
>>> print(new_a)
{'key': {'key_value': 'value', 'time': 0}}

Update

If instead, you want the current time, simply change the lambda function to time.time:

a={"key":{"key_value":"value", "time": time.time}}

Note that there are no parentheses after time.time. Everything else will work the same, except when you call get_my_dict(a), you will get the current time.

print(a)
{'key': {'key_value': 'value', 'time': <built-in function time>}}

new_a = mydict(a)
print(new_a)
{'key': {'key_value': 'value', 'time': 1516980015.325011}}

# wait a little and try again:
new_a = mydict(a)
print(new_a)
{'key': {'key_value': 'value', 'time': 1516980069.949716}}
pault
  • 41,343
  • 15
  • 107
  • 149