automatic accessors to a member var dict elements?

Jeff Shannon jeff at ccvcorp.com
Thu Oct 14 20:56:09 EDT 2004


Christopher J. Bottaro wrote:

>If I have the following class:
>
>class MyClass:
>        def __init__(self):
>                m_dict = {}
>                m_dict['one'] = 1
>                m_dict['two'] = 2
>                m_dict['three'] = 3
>
>  
>

First of all, you need to hold onto a copy of that dict if you want to 
be able to do anything with it.  You're creating m_dict as a local 
variable inside of __init__(), which goes out of scope when __init__() 
ends, and is then garbage-collected.  To get it to stay around, store it 
as an attribute of 'self' --

            self.m_dict = {}
            self.m_dict['one'] = 1
            self.m_dict['two'] = 2

and so on.

>Is there anyway to generate automatic accessors to the elements of the dict? 
>For example, so I could say:
>
>obj = MyClass()
>obj.one # returns obj.my_dict['one']
>obj.one = 'won' # same as obj.my_dict['one'] = 'won'
>  
>

If you want to be able to access these items as if they were plain 
attributes of your class instance, is there any reason why you're not 
just creating them as attributes?

    class MyClass:
        def __init___(self):
            self.one = 1

    obj = MyClass()
    obj.one  # --> 1
    obj.one = 'won'

If you really do need to maintain the dict separately, then you can use 
__getattr__() and __setattr__() to redirect accesses of nonexistent 
attributes into operations on your contained dict, something like this 
(untested):

    class MyClass(object):        # ensure a new-style class
        def __init__(self):
            self.m_dict = {'one':1, 'two':2, 'three':3}
        def __getattr__(self, attr):
            value = self.m_dict.get(attr, None)
            if value is None:
                raise AttributeError(attr)
            return value
        def __setattr__(self, attr, value):
            self.m_dict[attr] = value

I'm using a new-style class to take advantage of improvements in 
attribute lookup.  For this class, __getattr__()/__setattr__() will only 
be called if attr isn't found through the normal attribute resolution 
rules. 

One problem with the way I'm doing things here is that, if you set a 
dict item to a value of None, the object will raise an AttributeError 
when trying to access that item.  This really ought to use a safer 
sentinel value.  (Check for a recent thread here in c.l.py about 
sentinel values and the use of object() as one.)

It might be possible to use the mechanism you seem to want 
(automatically generating individual get/set methods, attaching them to 
the instance, creating a new property from the getter/setter), but that 
would involve significantly more complexity and magic, and would gain 
you very little (if anything).

Jeff Shannon
Technician/Programmer
Credit International





More information about the Python-list mailing list