namespace dictionaries ok?

Ron Adam rrr at ronadam.com
Tue Oct 25 17:49:38 EDT 2005



Bengt Richter wrote:
> On Tue, 25 Oct 2005 16:20:21 GMT, Ron Adam <rrr at ronadam.com> wrote:

>>Or worse, the dictionary would become not functional depending on what 
>>methods were masked.
>>
>>
>>And this approach reverses that, The dict values will be masked by the 
>>methods, so the values can't effect the dictionary methods.  But those 
>>specific values are only retrievable with the standard dictionary notation.
>>
>>    class namespace(dict):
>>        __getattr__ = dict.__getitem__
>>        __setattr__ = dict.__setitem__
>>        __delattr__ = dict.__delitem__
>>
>>    n = namespace()
>>    n.__getattr__ = 'yes'    # doesn't mask __getattr__ method.
>>
>>    print n['__getattr__']   -> 'yes'
>>
>>The value is there and __getattr__() still works.  But n.__getattr__ 
>>returns the method not the value.
>>
>>So is there a way to keep the functionality without loosing the methods?
>>
>>
>>BTW, I agree with Steven concerning data structures.  This really isn't 
>>a substitute for a data structure.  Many keys will not work with this.
>>
>>    n.my name = 'Ron'
>>    n.(1,2) = 25
>>    n.John's = [ ... ]
>>
>>The use case I'm thinking of is not as a shortcut for data structures, 
>>but instead, as a way to keep names as names, and maintaining those 
>>names in a group.  Thus the namespace association.
>>
>>   def foo(**kwds):
>>      kwds = namespace(kwds)
>>      print kwds.name
>>      print kwds.value
>>      ...
>>
>>   name = 'ron'
>>   value = 25
>>   foo( name=name, position=position )
>>
> 
> Just had the thought that if you want to add bindings on the fly modifying the
> original object, you could use the __call__ method, e.g.,
> 
>  >>> class NameSpace(dict):
>  ...     __getattr__ = dict.__getitem__
>  ...     __setattr__ = dict.__setitem__
>  ...     __delattr__ = dict.__delitem__
>  ...     def __call__(self, **upd):
>  ...         self.update(upd)
>  ...         return self
>  ...
>  >>> def show(x): print '-- showing %r'%x; return x
>  ...
>  >>> ns = NameSpace(initial=1)
>  >>> show(ns)
>  -- showing {'initial': 1}
>  {'initial': 1}
> 
> And updating with a second keyword on the fly:
> 
>  >>> show(show(ns)(second=2))
>  -- showing {'initial': 1}
>  -- showing {'second': 2, 'initial': 1}
>  {'second': 2, 'initial': 1}
> 
> FWIW ;-)
> 
> Regards,
> Bengt Richter

Getting better!  ;-)

That (or something similar) might avoid copying the whole thing in some 
situations, which is something I am concerned about.  But how to change 
a dict to a namespace without copying the contents item by item?

I'm not sure where or if this is going anywhere.  It may tie back into 
the properties groups example (see below) I posted earlier and keep 
finding improvements for.  ;-)

cheers,
    Ron




""" GPobject.py

Grouped Properties Object:

This need has presented itself while programming Tkinter
applications where a *LOT* of keywords are used. I think
property groups would also be good for general interface
building.  The external view is of a single cohesive
object, while the internal mechanism keeps the attributes
grouped so they can be forwarded easily as **kwds.

     class foo(GPobject):
         def __init__(self):
             self.properties(name, item_1, item_2, ... item_n)
             def getter():
                 ...
             def setter():
                 ...
             def remover():
                 ...
             self.name.doc( __doc__ string )
             self.name.get = getter
             self.name.set = setter
             self.name.remove = remover

     * The properties() method can also accept a dictionary.
     This will set both the names and the values at the same time.

         self.properties(name, dictionary)

         class myclass(GPobject):
             def __init__(self, **kwds):
                 self.properties('kwds', **kwds)

     * group.setup() allows easy initiation of get, set, remove,
     and doc group settings in one step.

         self.properties( name, *members )
         self.name.setup( get=myget, set='set', del='del',
                          doc='a property group' )

     * Using string flags to indicate default values lets you
     shorten the expression further.

         self.properties( name, *members )
         self.name.setup( myget, 'set', 'del', 'a property group')


The following is only somewhat tested... but it seems to work.
"""

class GPdict(dict):
     doc = "a property group"
     def doc(self, docstring): self.__doc__ = docstring
     def get(self, item): return self[item]
     def set(self, item, value): self[item] = value
     def remove(self, item): del self[item]
     def setup( self, fget='get', fset='set',
                        fdel='del', doc=doc ):
         if fget != 'get': self.get = fget
         if fset != 'set': self.set = fset
         if fdel != 'del': self.remove = fdel
         self.__doc__ = doc

     # Some useful common alternate methods to
     # replace get, set and remove.
     def readonly(self, *args):
         raise AttributeError, 'read only property'
     def setonce(self, item, value):
         if self[item] is None: self[item] = value
         else:
             raise AttributeError, 'set once property'
     def nonremovable(self, *args):
             raise AttributeError, 'non removable property'

class GPobject(object):
     """ an object that can use grouped properties """
     __properties__ = {}
     def __new__(cls, *args, **kwds):
         cls.__properties__ = {}
         return object.__new__(cls, *args, **kwds)
     def properties(self, *args, **kwds):
         dct = GPdict()
         for i in args[1:]:
             dct.setdefault(i,None)
         dct.update(kwds)
         self.__properties__[args[0]] = dct
         self.__dict__[args[0]] = dct
     def __getattr__(self, name):
         for dct in self.__properties__:
             if name in self.__properties__[dct]:
                 return self.__properties__[dct].get(name)
         return self.__dict__[name]
     def __setattr__(self, name, value):
         notprop = True
         for dct in self.__properties__:
             if name in self.__properties__[dct]:
                 self.__properties__[dct].set(name,value)
                 notprop = False
         if notprop:
             self.__dict__[name] = value
     def __delattr__(self, name):
         for dct in self.__properties__:
             if name in self.__properties__[dct]:
                 self.__properties__[dct].remove(name)
                 return
         del self.__dict__[name]



=================
     ### Properties as keyword sorter example,
     ### (sort to groups, not ordered sort)

     class sorter(GPobject):
         text_group = str.split('text fill font')
         line_group = str.split('line fill arrows')
         def __init__( self, text=None, fill=None, line=None,
                       arrows=None, font=None ):
             self.properties('_text', *self.text_group)
             self.properties('_line', *self.line_group)
             self.text = text
             self.fill = fill
             self.line = line
             self.arrows = arrows
             self.font = font

     s = sorter(text='hello', fill='black', line='solid', arrows='both')
     print 's._text =', s._text
     print 's._line =', s._line
     print s.__properties__




More information about the Python-list mailing list