possible attribute-oriented class

Ken Newton krnewton at gmail.com
Thu Sep 3 21:44:31 EDT 2009


On Thu, Sep 3, 2009 at 4:30 PM, Steven D'Aprano <
steve at remove-this-cybersource.com.au> wrote:

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

A couple extra details: The users are scientists, and technically
sophisticated.
They are used to specifying complicated sets of parameters and this
structured
form matches the way they are used to thinking about their work. Though they
are not programmers, they can define expressions to represent the desired
calculations for this project and occasionally write small programs in the
course
of their work. However, they will not like a long learning curve and will
want to be
isolated from most of the details in good programming design (error
handling,
creating supporting infrastructure, etc.)  In this case, Python will be used
as
a scripting language with most of the details specified by simple function
expressions
or defining structured data or specifying (linear) sequences of actions.

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


This is close to what I started with when I started exploring this idea.
But I felt I needed a way to create some additional support, that is
the str and repr functions.  These structures will be created and
populated once and saved in a python source file, which will be
loaded from the embedding C++ program.  The (scientist) users will
need a way to review the structure and current values while
interactively changing a few of the values to observe their effect on
the system.  My recursive __str__() and __repr__() functions were
intended to provide that support.


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


Good point. This was a placeholder. My intention was to add some
code to initialize the class from a dict. But didn't get around to
implementing that. Or the ideas I tried (couple years ago) didn't work.



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

Now, I can't remember why I ended up with my strange syntax.  Unless
it was related to the fact that I started doing this in IronPython and this
made it work better in that context or on the C# side of things.  I'm now
planning this for a CPython embedding situation.  And, perhaps as  you
pointed out, the __setitem__ isn't needed at all in the code I showed.


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


The getitem and delete behaviors are not expected to be common uses.
But if I continue with this approach, should be implemented for
completeness.

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

Yes, as mentioned above, I would like to initialize from a dict. Then the
given repr syntax would be a better fit. Appending a dict or concatenating
two or more objects might also be useful.  I'd also consider serializing to
an XML file, or a variation of the ConfigFile or *.ini  file formats if the
data
is kept to only a depth of 2 levels.



> --
> Steven
>

Thanks for all your comments.

Ken
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20090903/119d7f62/attachment.html>


More information about the Python-list mailing list