By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,243 Members | 1,141 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,243 IT Pros & Developers. It's quick & easy.

generic object implementation

P: n/a
So I'm trying to get a prototype implementation of the 'generic object'
type. (I'm currently calling it 'bunch', but only because I can't
really think of anything better.) I'd like some feedback on what
methods it needs to support. Ideally I'd keep this as minimal as
possible...

Remember that the goal of the 'generic object' type is to allow the
programmer to make the design decision that attribute-style access is
more appropriate than []-style access. Given that, my feeling is that
the 'generic object' type should *not* support __(get|set|del)item__ ,
though I'm still undecided on __len__, __iter__, __contains__, items,
keys, values, etc.

Here's what I have currently:

import operator as _operator

class bunch(object):
def __init__(self, **kwds):
self.__dict__.update(kwds)

def __eq__(self, other):
if not isinstance(other, bunch):
return False
attrs = set(self.__dict__)
if attrs != set(other.__dict__):
return False
for attr in attrs:
if not getattr(self, attr) == getattr(other, attr):
return False
return True

def __repr__(self):
return '%s(%s)' % (self.__class__.__name__,
', '.join('%s=%r' % (k, v)
for k, v in self.__dict__.items()))

def update(self, other):
self.__dict__.update(other.__dict__)

@classmethod
def frommapping(cls, mapping,
getkeys=iter, getitem=_operator.getitem):
result = bunch()
for key in getkeys(mapping):
value = getitem(mapping, key)
try:
value = bunch.frommapping(value)
except TypeError:
pass
setattr(result, key, value)
return result
Jul 18 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On Sun, 21 Nov 2004 23:55:48 GMT, Steven Bethard <st************@gmail.com> wrote:
So I'm trying to get a prototype implementation of the 'generic object'
type. (I'm currently calling it 'bunch', but only because I can't
really think of anything better.) I'd like some feedback on what
methods it needs to support. Ideally I'd keep this as minimal as
possible... UIAM 'bunch' already has a related meaning from c.l.py past (approx the first
three lines of your class), so how about 'gob' ? ;-)

Remember that the goal of the 'generic object' type is to allow the
programmer to make the design decision that attribute-style access is
more appropriate than []-style access. Given that, my feeling is that
the 'generic object' type should *not* support __(get|set|del)item__ ,
though I'm still undecided on __len__, __iter__, __contains__, items,
keys, values, etc.

Here's what I have currently:

import operator as _operator

class bunch(object):
def __init__(self, **kwds):
self.__dict__.update(kwds)

def __eq__(self, other):
if not isinstance(other, bunch):
return False
attrs = set(self.__dict__)
if attrs != set(other.__dict__):
return False
for attr in attrs:
if not getattr(self, attr) == getattr(other, attr):
return False
return True

def __repr__(self):
return '%s(%s)' % (self.__class__.__name__,
', '.join('%s=%r' % (k, v)
for k, v in self.__dict__.items()))

def update(self, other):
self.__dict__.update(other.__dict__)

@classmethod
def frommapping(cls, mapping,
getkeys=iter, getitem=_operator.getitem):
result = bunch()
for key in getkeys(mapping):
value = getitem(mapping, key)
try:
value = bunch.frommapping(value)
except TypeError:
pass
setattr(result, key, value)
return result


I dunno, begins to look more like a dict with getattr access substituted for __getitem__
than a primitive generic object...
class dbunch(dict): ... def __metaclass__(name, bases, cdict):
... cdict.update(dict.__dict__)
... cdict['__getattr__'] = cdict['__getitem__']
... cdict['__setattr__'] = cdict['__setitem__']
... cdict['__delattr__'] = cdict['__delitem__']
... def raiseunsub(*ignore): raise TypeError, 'unsubscriptable object'
... cdict['__getitem__'] = raiseunsub
... cdict['__setitem__'] = raiseunsub
... cdict['__delitem__'] = raiseunsub
... return type(name, bases, cdict)
... db = dbunch(x=123)
db {'x': 123} db.x 123 db['x'] Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 7, in raiseunsub
TypeError: unsubscriptable object db.y = 456
db {'y': 456, 'x': 123} db.x = 789
db {'y': 456, 'x': 789} del db.x
db {'y': 456} db.x = 101112
db.z = 131415
db {'y': 456, 'x': 101112, 'z': 131415} db.keys() ['y', 'x', 'z'] db.values() [456, 101112, 131415] db.items() [('y', 456), ('x', 101112), ('z', 131415)] for k in db: print k,

...
y x z

.... and etc. methods from dict, so should it be a restricted builtin subclass of dict
or derive from object directly? It the hope for a lean representation for small numbers
of items?

Regards,
Bengt Richter
Jul 18 '05 #2

P: n/a
Bengt Richter wrote:

UIAM 'bunch' already has a related meaning from c.l.py past (approx the first
three lines of your class), so how about 'gob' ? ;-)
Yeah, the intent is basically to provide that 3-liner. Could be that's
all that should be in the class... It wouldn't cover all my use cases,
but I'd certainly be happier with that than nothing.
I dunno, begins to look more like a dict with getattr access substituted for __getitem__
than a primitive generic object...
Yeah, the idea is to provide getattr access instead of __getitem__ --
that's basically what the original 3-liner does too. For my uses, I
don't think I'd ever want any of __len__, __iter__, __contains__, items,
keys, values, etc. but I wasn't the only one who seemed interested in
the idea... The pyparsing code in particular might benefit from
something like the frommapping method (and I know I could use it to
convert XML DOM into nested objects)...
>>> class dbunch(dict):

... def __metaclass__(name, bases, cdict):
... cdict.update(dict.__dict__)
... cdict['__getattr__'] = cdict['__getitem__']
... cdict['__setattr__'] = cdict['__setitem__']
... cdict['__delattr__'] = cdict['__delitem__']
... def raiseunsub(*ignore): raise TypeError, 'unsubscriptable object'
... cdict['__getitem__'] = raiseunsub
... cdict['__setitem__'] = raiseunsub
... cdict['__delitem__'] = raiseunsub
... return type(name, bases, cdict)
...


Interesting approach here. I hadn't thought of going this way. While I
hadn't planned on supporting the whole mapping interface, this would
certainly be an easy way to do so. I'll probably wait for a little more
feedback to see what the others who were interested want to use these
for... If people have good use cases for keys, items, etc. this is
probably the right answer...
It the hope for a lean representation for small numbers
of items?


Not exactly sure what you mean by lean...

All the use cases I have for it only care about 'obj.x' type access, and
don't really use any of the other container type methods. So in my
case, __init__, __eq__, __repr__, update and frommapping do pretty much
everything I want... If this is true for everyone else's use cases, I'd
rather not "pollute" the class with a bunch of dict methods... But I'm
certainly willing to be persuaded that other methods are also essential.

Steve
Jul 18 '05 #3

P: n/a
Steven Bethard wrote:
So I'm trying to get a prototype implementation of the 'generic object'
type. (I'm currently calling it 'bunch', but only because I can't
really think of anything better.) I'd like some feedback on what
Me neither. I called my bunch equivalent Struct, but that name seems
ambiguous because of the struct module.
methods it needs to support. Ideally I'd keep this as minimal as
possible...

Remember that the goal of the 'generic object' type is to allow the
programmer to make the design decision that attribute-style access is
more appropriate than []-style access. Given that, my feeling is that
the 'generic object' type should *not* support __(get|set|del)item__ ,
though I'm still undecided on __len__, __iter__, __contains__, items,
keys, values, etc.
Please, no. (except __iter__(), maybe)

Here's what I have currently:

import operator as _operator

class bunch(object):
def __init__(self, **kwds):
self.__dict__.update(kwds)

def __eq__(self, other):
Maybe just
return (type(self) == type(other)
and self.__dict__ == other.__dict__)

as you won't get properties right anyway.
Not sure whether that should be enforced, but subclassing bunch doesn't seem
a good idea to me.
if not isinstance(other, bunch):
return False
attrs = set(self.__dict__)
if attrs != set(other.__dict__):
return False
for attr in attrs:
if not getattr(self, attr) == getattr(other, attr):
return False
return True

def __repr__(self):
return '%s(%s)' % (self.__class__.__name__,
', '.join('%s=%r' % (k, v)
for k, v in self.__dict__.items()))

def update(self, other):
self.__dict__.update(other.__dict__)
I don't think update() is necessary, but if so, I'd rather have (untested)

def update(self, *other, **kw):
if other:
if len(other) != 1:
raise TypeError
other = other[0]
if isinstance(other, bunch):
other = other.__dict__
self.__dict__.update(other)
self.__dict__.update(kw)

i. e. something matching 2.4's dict.update() functionality as closely as
possible (and appropriate).

@classmethod
def frommapping(cls, mapping,
getkeys=iter, getitem=_operator.getitem):
result = bunch()
Substitute bunch with cls throughout.
Should there also be a getpairs argument that would yield (key, value)
pairs?
for key in getkeys(mapping):
value = getitem(mapping, key)
try:
value = bunch.frommapping(value)
except TypeError:
pass
setattr(result, key, value)
return result


Seeing how many aspects are to consider with such a simple thing as a bunch,
it would really be a benefit if one standard approach were available to
substitute all the ad hoc solutions currently out there in the wild.
Good luck with your effort.

Peter

Jul 18 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.