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