Inheriting dictionary

P

Pavel Panchekha

I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.
 
J

Jan Kaliszewski

18-08-2009 o 21:44:55 Pavel Panchekha said:
I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.

AFAIN -- no. But you can easily implement it in Python with rather
small loss of speed...


class InheritDict(dict):

class NoParent(object):
def __getitem__(self, key):
raise KeyError('There is no %r key in the hierarchy' % key)
def __nonzero__(self):
return False

noparent = NoParent()

def __init__(self, *args, **kwargs):
parent = kwargs.pop('inherit_from', self.noparent)
dict.__init__(self, *args, **kwargs)
self.parent = parent

def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.parent[key]


Did you do it in similar way? (just curiosity) :)

Regards,
*j
 
P

Pavel Panchekha

I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:
"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)
a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""
I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.

AFAIN -- no. But you can easily implement it in Python with rather
small loss of speed...

  class InheritDict(dict):

      class NoParent(object):
          def __getitem__(self, key):
              raise KeyError('There is no %r key in the hierarchy' % key)
          def __nonzero__(self):
              return False

      noparent = NoParent()

      def __init__(self, *args, **kwargs):
          parent = kwargs.pop('inherit_from', self.noparent)
          dict.__init__(self, *args, **kwargs)
          self.parent = parent

      def __getitem__(self, key):
          try:
              return dict.__getitem__(self, key)
          except KeyError:
              return self.parent[key]

Did you do it in similar way? (just curiosity) :)

Regards,
*j

I implemented it in a similar way (instead of a try block, an if
block, which works a tiny bit faster; also have a multiple-parents
case, but its rare, and I could do that in Python without much loss of
speed). Pity that there's no C version; this InheritDict is kind of
the core of my application (in a very basic test, I have 329901 calls
to __getitem__).

Oh well; I'll see if I can optimize the __getattr__ function with
minor tweaking. Thanks for your help.
 
J

Jan Kaliszewski

18-08-2009 o 22:27:41 Nat Williams said:
I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.


Why complicate this with a custom object? Just use regular dicts and
make b a copy of a.

a = {1: 'one', 2: 'two', 4: 'four'}
b = dict(a)
b[3] = 'three'
b[4] = 'foobar'

Because, as I understand Pavel's intent, it has to work dynamically
(e.g. changes in 'a' reflect in behaviour of 'b'), and obviously not
only for such trivial examples like above.

*j
 
P

Pavel Panchekha

On Tue, Aug 18, 2009 at 2:44 PM, Pavel Panchekha  
I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:
"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)
a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""
I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.
Why complicate this with a custom object?  Just use regular dicts and  
make b a copy of a.
a = {1: 'one', 2: 'two', 4: 'four'}
b = dict(a)
b[3] = 'three'
b[4] = 'foobar'

Because, as I understand Pavel's intent, it has to work dynamically
(e.g. changes in 'a' reflect in behaviour of 'b'), and obviously not
only for such trivial examples like above.

*j

That is indeed the point.
 
S

Simon Forman

I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.


I would consider something like the following:


a = {1: "one", 2: "two", 4: "four"}
b = {3: "three", 4: "foobar"}


from functools import partial


def getter(first, second, key):
try:
return first(key)
except KeyError:
return second(key)


f = partial(getter, b.__getitem__, a.__getitem__)


# Or, if you know you'll be getting a lot of KeyErrors, you
# can use get() instead of __getitem__().

def getter1(first, second, key, sentinel=None):
item = first(key, sentinel)
if item is sentinel:
item = second(key)
return item

g = partial(getter1, b.get, a.__getitem__)


HTH,
~Simon
 
S

Simon Forman

I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.


I would consider something like the following:


a = {1: "one", 2: "two", 4: "four"}
b = {3: "three", 4: "foobar"}


from functools import partial


def getter(first, second, key):
   try:
       return first(key)
   except KeyError:
       return second(key)


f = partial(getter, b.__getitem__, a.__getitem__)


# Or, if you know you'll be getting a lot of KeyErrors, you
# can use get() instead of __getitem__().

def getter1(first, second, key, sentinel=None):
   item = first(key, sentinel)
   if item is sentinel:
       item = second(key)
   return item

g = partial(getter1, b.get, a.__getitem__)


HTH,
~Simon

Since you're going for speed the overhead of using partial (which
creates a wrapper object around the getter function) can be replaced
by something like this:

def makeGetter(first, second):
def getter(key):
try:
return first(key)
except KeyError:
return second(key)
return getter


f = makeGetter(b.__getitem__, a.__getitem__)
 
H

Hendrik van Rooyen

I want a dictionary that will transparently "inherit" from a parent
dictionary. So, for example:

"""
a = InheritDict({1: "one", 2: "two", 4: "four"})
b = InheritDict({3: "three", 4: "foobar"}, inherit_from=a)

a[1] # "one"
a[4] # "four"
b[1] # "one"
b[3] # "three"
b[4] # "foobar"
"""

I've written something like this in Python already, but I'm wondering
if something like this already exists, preferably written in C, for
speed.

Its not inheritance, but have you looked at the update method?

-Hendrik
 

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,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top