dynamic variable referencing

Heiko Wundram modelnine at bit-bukket.org
Wed Dec 7 00:23:06 EST 2005


Michael Williams wrote:
> -  I don't want to say     OBJECT.VAR      but rather      OBJECT.
> ("string")      and have it retrieve the variable (not the value of
> it) if in fact it exists. . .
>
> <snip>
>

It's not exactly clear what you're trying to tell us here. Basically, what I
guess you want is:

getattr(object,"varname")

This retrieves the value that is bound to varname at "namespace" object. You
cannot retrieve a variable per se in Python, as a variable is just a name
that is a binding to an object.

The second part of what you're trying to do sounds more like stacking
objects. I'll just give it a shot and implement a little bit to test on.
You'll have to extend it to suit your needs... ;-)

class xmlnode(object):

    def __init__(self):
        self.__subnodes = {}
        self.__value = ""

    def __getattr__(self,item):
        if item == "value":
            return self.__value
        elif item.startswith("_"):
            raise AttributeError, item
        elif item not in self.__subnodes:
            self.__subnodes[item] = xmlnode()
        return self.__subnodes[item]

    def __setattr__(self,item,value):
        if item.startswith("_"):
            super(xmlnode,self).__setattr__(item,value)
        elif item == "value":
            assert isinstance(value,(str,unicode))
            self.__value = value
        else:
            assert isinstance(value,(str,unicode))
            if item not in self.__subnodes:
                self.__subnodes[item] = xmlnode()
            self.__subnodes[item].value = value

    def __delattr__(self,item):
        if item.startswith("_"):
            super(xmlnode,self).__delattr__(item)
        elif item == "value":
            self.__value = None
        else:
            try:
                del self.__subnodes[item]
            except KeyError:
                raise AttributeError, item

    def toXML(self,name):
        rv = ["<%s>" % name]
        for sname, sitem in self.__subnodes.iteritems():
            rv.append(sitem.toXML(sname))
        if self.__value is not None:
            rv.append(self.__value)
        rv.append("</%s>" % name)
        return "".join(rv)

This implements a simple XML-tree builder with a very specific output format
(tags contain only one string value, which always comes after any subtag
that they might contain, and subtag order is random). The "tricky" part is
in the __*attr__ logic to get subnodes.

Example of usage:

>>> a = test.xmlnode()
>>> a
<test.xmlnode object at 0x2aaaaab57890>
>>> a.value = "test"
>>> a.toXML("root")
'<root>test</root>'
>>> a.book = "welcome"
>>> a.anotherbook = "bye"
>>> a.toXML("root")
'<root><anotherbook>bye</anotherbook><book>welcome</book>test</root>'
>>> a.book.value
'welcome'
>>> a.book.anotherbook.somethingelse.thisislong = "test"
>>> a.toXML("root")
'<root><anotherbook>bye</anotherbook><book><anotherbook><somethingelse><thisislong>test</thisislong></somethingelse></anotherbook>welcome</book>test</root>'
>>>

HTH!

--- Heiko.



More information about the Python-list mailing list