how to detect if a dictionary has been modified ?

S

Stef Mientki

hello,

Just like in a normal text editor,
I would like to detect if a dictionary has been changed.
So I would like to have a modified-flag.
(This dictionary is used as a communication channel between processes)

Now I do it to make a copy of the dictionary and compare it with the old
one.
When a change is detected I nake a new copy and interpret the whole new
dictionary again,
so I'm not interested in knowing where the change(s) are located.
This works well, but as I have many of these dictionaries,
I find the copy a waste of time and space.

Has anyone derived a new dictionary with a modified flag ?
Or are there other solutions to detect easily a directory change ?

thanks,
Stef Mientki
 
B

bearophileHUGS

Stef Mientki:
I would like to detect if a dictionary has been changed.
So I would like to have a modified-flag.

A solution is of course to create a SDict class, that works like a
normal dict, and also watches for changes and has an extra boolean
attribute.

Bye,
bearophile
 
S

Steven D'Aprano

Stef Mientki:

A solution is of course to create a SDict class, that works like a
normal dict, and also watches for changes and has an extra boolean
attribute.

What does the S stand for?

Untested and possibly incomplete:

def factory(methodname, cls=dict, flag=True):
def method(self, *args, **kwargs):
self.modified = flag
return getattr(cls, methodname)(self, *args, **kwargs)
return method


class SDict(dict):
__init__ = factory('__init__', flag=False)
__setitem__ = factory('__setitem__')
__delitem__ = factory('__delitem__')
clear = factory('clear')
pop = factory('pop')
popitem = factory('popitem')
setdefault = factory('setdefault')
update = factory('update')
 
P

Paul Rubin

Stef Mientki said:
Now I do it to make a copy of the dictionary and compare it with the
old one.
When a change is detected I nake a new copy and interpret the whole
new dictionary again,
so I'm not interested in knowing where the change(s) are located.
This works well, but as I have many of these dictionaries,
I find the copy a waste of time and space.

As a couple of people have said, you could make a dict subclass that
notices when you do updates. I think the real answer is a
"functional" dictionary, which means one that is never updated. You
instead make a new functional dictionary that shares structure with
the old one. The functional dictionary uses a balanced-tree data
structure that makes this creation of new partially-shared
dictionaries efficient. Look up "AVL tree" or "red-black tree" for
how they work.

I've been wanting for a while to get around to coding some of these
structures in Python, but I'll be even happier if someone else beats
me to it.
 
B

bearophileHUGS

Paul Rubin:
As a couple of people have said, you could make a dict subclass that
notices when you do updates.  I think the real answer is a
"functional" dictionary, which means one that is never updated.

Python V. 2.4, 2.5, 2.6. 3.0 have gained more and more lazy-style
features, this is changing a little how normal Python programs are
written (compared for example with Haskell, using lazy computations in
Python is less handy and probably less safe too, because for example
in Haskell you can define something that lazily generates an infinite
sequence of items, this is now easy to do in Python too, but in
Haskell inside the generator you can use items generated in the past
too, and the generators don't exhaust).

In the last years functional languages are raising their elegant
lambda-shaped heads more and more, so today you can find several
immutable data structures in Scala and F# languages (and in the D
language true closures, simple ways to state recursively immutable
things, and even pure functions. This will make D like a cleaned up,
simplified and improved C++ with functional features added. Then D3
may add AST macros. At that point pattern-matching programming,
dataflow programming, constraint programming and Logic programming
become the few programming styles not supported natively).

So maybe in the following years Python too may gain few other
immutable data structures, fitter for a functional style of
programming (in Python there are already some immutable data
structures, like strings, tuples, frozensets, and I sometimes use
frozendicts. Time objects and time deltas too are often good kept as
immutable).

Bye,
bearophile
 
G

Glenn Linderman

A solution is of course to create a SDict class, that works like a
normal dict, and also watches for changes and has an extra boolean
attribute.

What does the S stand for?

Untested and possibly incomplete:

def factory(methodname, cls=dict, flag=True):
def method(self, *args, **kwargs):
self.modified = flag
return getattr(cls, methodname)(self, *args, **kwargs)
return method


class SDict(dict):
__init__ = factory('__init__', flag=False)
__setitem__ = factory('__setitem__')
__delitem__ = factory('__delitem__')
clear = factory('clear')
pop = factory('pop')
popitem = factory('popitem')
setdefault = factory('setdefault')
update = factory('update')
[/QUOTE]

Interesting technique. I must point out, though, that it doesn't
indicate if a dict has been changed, only that potentially changing
operations have been performed. So it really depends on what Stef
originally meant by changed, and perhaps what is meant by == :)

x = {'a', 3}
x['a'] = 3

Whether x has been changed by the second statement is the open
question. The above code would declare it has, but most people, when
shown before and after copies of the dict, with declare it hasn't.
 
A

Arnaud Delobelle

Glenn Linderman said:
Interesting technique. I must point out, though, that it doesn't
indicate if a dict has been changed, only that potentially changing
operations have been performed. So it really depends on what Stef
originally meant by changed, and perhaps what is meant by == :)

x = {'a', 3}

You mean x = {'a': 3}!
x['a'] = 3

Whether x has been changed by the second statement is the open
question. The above code would declare it has, but most people, when
shown before and after copies of the dict, with declare it hasn't.

Good point. What about

Has d changed or not?
 
S

Steven D'Aprano

Interesting technique. I must point out, though, that it doesn't
indicate if a dict has been changed, only that potentially changing
operations have been performed. [...]
The above code would declare it has, but most people, when shown before
and after copies of the dict, with declare it hasn't.

Oh I agree entirely. But I'm not going to do *all* the work for the
original poster :)
 
G

Glenn Linderman

You mean x = {'a': 3}!

Indeed I did, thanks for the correction.
x['a'] = 3

Whether x has been changed by the second statement is the open
question. The above code would declare it has, but most people, when
shown before and after copies of the dict, with declare it hasn't.

Good point. What about

d = {1: []}
d[1].append(2)

Has d changed or not?

Which just goes to show that the SDict implementation above is, as
suspected by the author, incomplete for the purpose of detecting all
changes to the dict, as well as detecting some that might not be
perceived as changes.
 
S

Stef Mientki

Good point. What about

d = {1: []}
d[1].append(2)

Has d changed or not?

Which just goes to show that the SDict implementation above is, as
suspected by the author, incomplete for the purpose of detecting all
changes to the dict, as well as detecting some that might not be
perceived as changes.
I now see there's no simple solution.
And above my normal copy also doesn't work in the above case.
So for the moment I'll use a deepcopy,
hopes that work.
In the future I'll see if it's possible that the "changer" will set the
modify flag.

thank you all for the contributions.

Paul and "bearophile", you talks about "functional" languages and
balanced trees are a bit too high for my knowledge,
all though the program in which I need this is a functional language
environment and based on dataflow programming ;-)

cheers,
stef
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top