[Tutor] new object attribute from string?

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon Apr 14 16:20:02 2003


On Mon, 14 Apr 2003 alan.gauld@bt.com wrote:

> > It is possible to dynamically add new attributes to our objects.  Each
> > object in Python has an internal '__dict__' dictionary that
> > keeps track of all of its attributes:
> >
> > ###
> > >>> class TestAttribute:
> > ...     def __init__(self, name):
> > ...         self.name = name
> > ...     def printInternals(self):
> > ...         print "my dictionary looks like this:", self.__dict__
> >
> > And we're already very familiar with dictionaries: we can
> > easily add new attributes by assigning another key to
> > that __dict__ionary.
>
> But since we can achieve the same by simply assigning to a new attribute
> there is no need for such complexity
>
> >>> t1.question = 'new object attribute from string?'
>
> Achieves the same result
>
> > >>> t1.question
> > 'new object attribute from string?'


[warning; slightly advanced code ahead]

Hi Alan,

Yes, the direct way works too.  *grin*

In certain really dynamic code, the attribute name itself may not known
until "runtime", when the program is actively running.


For example, here's a toy class that demonstrates the kind of dynamism we
can do in Python:

###
from __future__ import nested_scopes

class PleaseWrapper(object):
    """Wraps around an object and puts a please()ing wrapper around every
       attribute of our class."""
    def __init__(self, wrapped_object):
        self.__wrapped_object = wrapped_object
        for key, value in self.__wrapped_object.__dict__.items():
            self.__dict__[key] = self.__makePleaseFunction(key, value)
    def __makePleaseFunction(self, key, value):
        class F(str):
            def __init__(self2, message):
                str.__init__(self2, message)
                self2.__key = key
                self2.__value = value
            def please(self2):
                return self2.__value
        return F("say please()!")
###


The code may look a bit mysterious: what does it do?  Well, let's say that
we had some class instance, like:

###
>>> class Person(object):
...     def __init__(self, name):
...         self.name = name
...
>>> p = Person("Danny")
>>> p.name
'Danny'
###

and let's say that we wanted it to be a little, well, annoying.  *grin* We
can make another instance that looks like 'p', but forces us to ask it
'please()' to get the value of anything:

###
>>> p2 = PleaseWrapper(p)
>>> p2.name
'say please()!'
>>> p2.name.please()
'Danny'
###


This sort of dynamicism is possible when we can manipulate an object's
attributes through the dictionary interface.


Hope this helps!