__getattr__ weirdness

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Greg Brunet

    __getattr__ weirdness

    In adding the ability to refer to field values using dbfFile.field
    notation, I learned how to use __getattr__ and __setattr__ . After some
    trial and error, I got it working. But as part of my trials, I added
    some print statements to debug stuff. The ones I added to __setattr__
    work as expected, but the one in __getattr__ seems to get called just
    under 1000 times for every __getattr__ call!

    Something is obviously not right here - but I'm at a loss to understand
    what's going on. I've pared down my code to still show it happening &
    included it below. If you run this program & pipe the output to a file,
    you'll get just under 14000 debug lines. Any ideas? Thanks!

    --
    Greg


    # ----------------------------------------------------------------------
    ----------
    class test:
    """Introspectio n test"""

    #----------------------------------------
    def __init__(self,f ilename):
    print '** __init__'
    self._filename= filename
    self._del=' '
    self._dirty=Fal se
    self._open=Fals e
    self._rec=[]
    self._recno = 1

    #----------------------------------------
    def __getattr__(sel f, key):
    """ Return DBF record values by field name """
    print "_ga: " + key
    try:
    return self._rec[self._fldNames. index(key.upper ())]
    except:
    raise AttributeError( "Unknown Field: %s" % ( key ))

    #----------------------------------------
    def __setattr__(sel f, key, val):
    """ Update DBF record values by field name """
    print "_sa: %s: %s" % (key, val)
    try:
    self._rec[self._fldNames. index(key.upper ())] = val
    print " (DBF field assignment)"
    except:
    self.__dict__[key] = val # use the regular variable!
    #raise AttributeError( "Unknown Field: %s" % ( key ))

    #----------------------------------------
    #----------------------------------------
    if __name__ == "__main__":

    f = test('test.dbf' )
    f._del='*'
    f._recno=123
    f._recno=1
    f._recno=2
    f._recno=3
    f._recno=4
    f._recno=5
    f._recno=6

  • Greg Brunet

    #2
    Re: __getattr__ weirdness

    I've figured out one thing: that be re-arranging the __init__ code
    assignments (and adding one that was placed later in code I snipped
    out), I am able to get the extra _ga calls to stop a lot earlier. This
    code:

    #----------------------------------------
    def __init__(self,f ilename):
    print '** __init__'
    self._rec=[]
    self._fldNames=[]
    self._filename= filename
    self._del=' '
    self._dirty=Fal se
    self._open=Fals e
    self._recno = 1

    .... by assigning _rec & _fldNames first, gets the repeated _ga calls to
    stop after the first assignment following those two assignments. I'm
    still at a loss as to why _ga is being called all these times to begin
    with though! I'm only assigning values, not requesting them! Thanks,

    --
    Greg

    Comment

    • Stephan Diehl

      #3
      Re: __getattr__ weirdness

      Greg Brunet wrote:
      [color=blue]
      > In adding the ability to refer to field values using dbfFile.field
      > notation, I learned how to use __getattr__ and __setattr__ . After some
      > trial and error, I got it working. But as part of my trials, I added
      > some print statements to debug stuff. The ones I added to __setattr__
      > work as expected, but the one in __getattr__ seems to get called just
      > under 1000 times for every __getattr__ call!
      >
      > Something is obviously not right here - but I'm at a loss to understand
      > what's going on. I've pared down my code to still show it happening &
      > included it below. If you run this program & pipe the output to a file,
      > you'll get just under 14000 debug lines. Any ideas? Thanks!
      >[/color]

      Within the __getattr__ method, you can't just do normal attribute access as
      this will trigger another call to __getattr__, so you where stuck in an
      infinite loop.
      try to access the required attribute directly from the __dict__

      def __getattr__(sel f, key):
      """ Return DBF record values by field name """
      print "_ga: " + key
      try:
      # return self._rec[self._fldNames. index(key.upper ())]
      ^^^^
      return self.__dict__['_rec'][self._fldNames. index(key.upper ())]
      except:
      raise AttributeError( "Unknown Field: %s" % ( key ))

      Hope that helps

      Stephan

      Comment

      • Greg Brunet

        #4
        Re: __getattr__ weirdness

        "Stephan Diehl" <stephan.diehl@ gmx.net> wrote in message
        news:bi5ofn$uo3 $04$1@news.t-online.com...[color=blue]
        > Within the __getattr__ method, you can't just do normal attribute[/color]
        access as[color=blue]
        > this will trigger another call to __getattr__, so you where stuck in[/color]
        an[color=blue]
        > infinite loop.
        > try to access the required attribute directly from the __dict__
        >
        > def __getattr__(sel f, key):
        > """ Return DBF record values by field name """
        > print "_ga: " + key
        > try:
        > # return self._rec[self._fldNames. index(key.upper ())]
        > ^^^^
        > return[/color]
        self.__dict__['_rec'][self._fldNames. index(key.upper ())][color=blue]
        > except:
        > raise AttributeError( "Unknown Field: %s" % ( key ))
        >
        > Hope that helps
        >
        > Stephan[/color]

        Hey Stephan:

        That did the trick! Actually, I had to do the same for self._fldNames
        as well. Also, I changed them in the _sa code section instead of the
        _ga code, since now that I look at it again with a little better
        understanding, the original _sa code was referring to the _rec &
        _fldNames variables/attributes directly, so as long as they weren't
        defined, it was triggering the _ga calls. So now the _ga code doesn't
        get called unless I specifically ask for it - like I would want. The
        code now looks like:

        #----------------------------------------
        def __getattr__(sel f, key):
        """ Return DBF record values by field name """
        print "_ga: " + key
        try:
        return self._rec[self._fldNames. index(key.upper ())]
        except:
        raise AttributeError( "Unknown Field: %s" % ( key ))

        #----------------------------------------
        def __setattr__(sel f, key, val):
        """ Update DBF record values by field name """
        print "_sa: %s: %s" % (key, val)
        try:

        self.__dict__['_rec'][self.__dict__['_fldNames'].index(key.uppe r())] =
        val
        print " (DBF field assignment)"
        except:
        self.__dict__[key] = val # use the regular variable!
        #raise AttributeError( "Unknown Field: %s" % ( key ))

        Thanks for everyone's help!

        --
        Greg


        Comment

        Working...