possible attribute-oriented class

K

Ken Newton

I have created the following class definition with the idea of making
a clean syntax for non-programmers to created structured data within a
python environment.

I would appreciate comments on this code. First, is something like
this already done? Second, are there reasons for not doing this? If
this seems OK, how could I clean up the string conversion to have
indented format.

The expected use would have all items in the structure be simple
python types or AttrClass types. Code written in python could walk the
structure in a simple way to locate any desired values. Code in a
C/C++ extension should also be able to walk the structure to use any
value in the structure.

class AttrClass(object):
"""AttrClass lets you freely add attributes in nested manner"""

def __init__(self):
pass
def __setitem__(self, key, value):
return self.__dict__.__setitem__(key, value)
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, self.__dict__.__repr__())
def __str__(self):
ll = ['{']
for k,v in self.__dict__.iteritems():
ll.append("%s : %s" % (k, str(v)))
return '\n'.join(ll) + '}'

def test():
atr = AttrClass()
atr.first = 1
atr.second = 2
atr.third = 'three'

atrsub = AttrClass()
atrsub.aaa = 'AAA'
atrsub.bbb = 'BBB'

atr.fourth = atrsub
atr.fifth = 5

print atr
print
print repr(atr)
print
print atr.fourth.aaa
=========
test() gives the following output:
----
{
second : 2
fifth : 5
fourth : {
aaa : AAA
bbb : BBB}
third : three
first : 1}

AttrClass({'second': 2, 'fifth': 5, 'fourth': AttrClass({'aaa': 'AAA',
'bbb': 'BBB'}), 'third': 'three', 'first': 1})

AAA
 
S

Steven D'Aprano

I have created the following class definition with the idea of making a
clean syntax for non-programmers to created structured data within a
python environment.

What do you expect non-programmers to do with this class, without
programming? How can they even use it?


....
The expected use would have all items in the structure be simple python
types or AttrClass types. Code written in python could walk the
structure in a simple way to locate any desired values. Code in a C/C++
extension should also be able to walk the structure to use any value in
the structure.

I don't see the purpose of it. Nested data structures are generally
harder for people to understand than non-nested ones, hence the Python
Zen: "flat is better than nested". For example, a list is easier to grasp
than a tree. This especially applies to non-programmers.

I don't see how this is simple enough for non-programmers, or useful for
programmers. For programmers, just nest objects:

class Parrot(object):
pass

obj = Parrot()
obj.x = 1
obj.y = Parrot()
obj.y.z = 2
obj.y.z.zz = Parrot()



class AttrClass(object):
"""AttrClass lets you freely add attributes in nested manner"""

You don't actually need a special class for that, unless you're providing
extra functionality. A bare subclass of object will let you freely add
attributes in a nested manner.

It seems to me that you're combining two different sets of functionality,
but only describing one. The first is, nested attributes -- but you get
that for free with any class. The second is the ability to set (but
strangely not retrieve!) attributes using dictionary-like syntax. But
that's implied by the code, you haven't mentioned it in your description
or documentation.

def __init__(self):
pass

If the __init__ method doesn't do anything, you don't need it.

def __setitem__(self, key, value):
return self.__dict__.__setitem__(key, value)

Simpler to just say:

def __setitem__(self, key, value):
self.__dict__[key] = value

You don't strictly need the return, because methods return None by
default, and dict.__setitem__ always returns None (unless it raises an
exception).


This method allows you to set attributes using dict syntax:

instance['key'] = 123 # same as instance.key = 123

But you don't have corresponding __getitem__ or __delitem__ methods, so
you can't do these:

value = instance['key'] # fails
del instance['key'] # fails


def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
self.__dict__.__repr__())

This strongly implies that you should be able to create a new instance
using that format:

AttrClass({'key': 123, 'another_key': 456})

but that fails. As a general rule, the repr() of a class should (if
possible) work correctly if passed to eval(). This doesn't. That's not
entirely wrong, but it is unusual and confusing.
 
P

Peter Otten

Ken said:
class AttrClass(object):
"""AttrClass lets you freely add attributes in nested manner"""

def __init__(self):
pass
def __setitem__(self, key, value):
return self.__dict__.__setitem__(key, value)
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
self.__dict__.__repr__())
def __str__(self):
ll = ['{']
for k,v in self.__dict__.iteritems():
ll.append("%s : %s" % (k, str(v)))
return '\n'.join(ll) + '}'

def test():
atr = AttrClass()
atr.first = 1
atr.second = 2
atr.third = 'three'

atrsub = AttrClass()
atrsub.aaa = 'AAA'
atrsub.bbb = 'BBB'

atr.fourth = atrsub
atr.fifth = 5

print atr
print
print repr(atr)
print
print atr.fourth.aaa

Just in case you didn't note: your test() function will run successfully
even if you remove the __setitem__() method. Allowing

atr["x"] = 42

but not

print attr["x"]

may puzzle your intended audience.
 

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,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top