__getattr__ and __setattr__ troubles
Adam Ruth
aruth at intercation.com
Wed May 24 10:15:33 EDT 2000
Here's your problem:
> def setFieldValue(self, field, value):
> print "Call: setFieldValue", field, value
> if self._tblDef.has_key(field):
> self._fields[field]=value
> else:
> self.__dict__[field]=value
Since _tblDef doesn't have a "field3", then field3 will be set in
the __dict__, not in the _fields as you might expect.
The __str__ and __coerce__, etc, will all be sent to
__getattr__ because they are *not* defined in the
class. If they were, then __getattr__ would never be
called.
You'll notice that on the print "3", myrec.field3 call, that
__getattr__ is never called, that's because setFieldValue
put it in __dict__.
Hope this helps.
--
Adam Ruth
InterCation, Inc.
www.intercation.com
"Boudewijn Rempt" <boud at rempt.xs4all.nl> wrote in message
news:8gehq1$kq6$1 at news1.xs4all.nl...
> I'm playing with a kind of generic record class that should keep
> a dictionary of fields and values besides a lot of housekeeping
> stuff. I want the fields also to be available using record.field
> notation.
>
> I thought I'd use __getattr__ and __setattr__ for it, but I was quite
> surprised by the results, and I really hope someone can put me right!
>
> From the documentation I understood that __getattr__ is only called when
> the ordinary normal mechanism fails. However, I see it being called even
> when my app needs things like __cmp__ and __repr__. though not for the
> fields I added myself after creating the object.
>
> This is my script:
>
> #!/usr/bin/env python
> class dbRecord:
>
> def __init__(self, tblDef, fields={}):
> self._tblDef=tblDef
> self._fields=fields
>
> def __getattr__(self, name):
> print "Call: __getattr__", name
> if self.__dict__.has_key("_fields"):
> return self.getFieldValue(name)
> else:
> return self.__dict__[name]
>
> def __setattr__(self, name, value):
> print "Call: __setattr__", name, value
> if self.__dict__.has_key("_fields"):
> self.setFieldValue(name, value)
> else:
> self.__dict__[name]=value
>
> def getFieldValue(self, field):
> """
> return the value of a field in the record.
> """
> print "Call: getFieldValue", field
> if self._fields.has_key(field):
> return self._fields[field]
> else:
> if self._tblDef.has_key(field):
> self._fields[field]=None
> return None
> else:
> return self.__dict__[field]
>
> def setFieldValue(self, field, value):
> print "Call: setFieldValue", field, value
> if self._tblDef.has_key(field):
> self._fields[field]=value
> else:
> self.__dict__[field]=value
>
> def getFields(self):
> return self._fields
>
> def main():
> tblDef={"field1": "aField", "field2": "anotherField"}
> fields={"field1": "contents"}
> myrec=dbRecord(tblDef, fields)
> myrec.field2="aaa"
> myrec.field3="bbb"
> print "1", myrec.field1
> print "2", myrec.field2
> print "3", myrec.field3
> for fieldname, value in myrec.getFields().items():
> print fieldname, value
> print "myrec:", myrec
> myrec2=dbRecord(tblDef, fields)
> if myrec==myrec2:
> print "same"
> else:
> print "different"
>
>
> if __name__=="__main__":
> main()
>
> And this is the suprising output:
>
> bash-2.03$ dbobj.py
> Call: __setattr__ _tblDef {'field1': 'aField', 'field2':
> 'anotherField'}
> Call: __setattr__ _fields {'field1': 'contents'}
> Call: __setattr__ field2 aaa
> Call: setFieldValue field2 aaa
> Call: __setattr__ field3 bbb
> Call: setFieldValue field3 bbb
> 1 Call: __getattr__ field1
> Call: getFieldValue field1
> contents
> 2 Call: __getattr__ field2
> Call: getFieldValue field2
> aaa
> 3 bbb
> field1 contents
> field2 aaa
> myrec: Call: __getattr__ __str__
> Call: getFieldValue __str__
> Call: __getattr__ __repr__
> Call: getFieldValue __repr__
> <__main__.dbRecord instance at 80e9170>
> Call: __setattr__ _tblDef {'field1': 'aField', 'field2':
> 'anotherField'}
> Call: __setattr__ _fields {'field1': 'contents', 'field2': 'aaa'}
> Call: __getattr__ __coerce__
> Call: getFieldValue __coerce__
> Call: __getattr__ __cmp__
> Call: getFieldValue __cmp__
> Traceback (innermost last):
> File "./dbobj.py", line 66, in ?
> main()
> File "./dbobj.py", line 59, in main
> if myrec==myrec2:
> File "./dbobj.py", line 11, in __getattr__
> return self.getFieldValue(name)
> File "./dbobj.py", line 34, in getFieldValue
> return self.__dict__[field]
> KeyError: __cmp__
>
> I hope the solution is fairly simple and that I've only misread
> something ;-).
>
> --
>
> Boudewijn Rempt | http://www.valdyas.org
More information about the Python-list
mailing list