possible attribute-oriented class

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Sep 4 01:30:53 CEST 2009


On Thu, 03 Sep 2009 15:46:01 -0700, Ken Newton wrote:

> 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.




-- 
Steven



More information about the Python-list mailing list