[Tutor] Using __setattr__ (fwd)

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon Apr 21 01:53:01 2003


Hi Tony,

Let me send this off to tutor@python.org too --- this'll let other people
jump in when I say something screwy or totally wrong... *grin*


> With that in mind, I guess I could call the function you wrote below,
> from __init__() ???

Yes!  We can send that source string as a parameter to the __init__
method, and have __init__ delegate some of the work off to that
hypothetical initWithString() method.

Talk to you later!



---------- Forwarded message ----------
Date: Sun, 20 Apr 2003 20:53:32 -0700
From: Tony Cappellini <tony@tcapp.com>
To: Danny Yoo <dyoo@hkn.eecs.berkeley.edu>
Subject: Re: [Tutor] Using __setattr__


Hi Danny,

thanks for the advice.

Since this class isn't intended to be derived from, or used by other
people/programs,
I want the string to be parsed during class instantiation.
I also don't want any methods to be called explicitly by the caller.
Pass the string in, and that's it.

With that in mind, I guess I could call the function you wrote below, from
__init__() ???

>The code can actually be rewritten to avoid __setattr__ altogether: how
>about just adding a method called initFromString()?
>
>###
>     def initFromString(self, name, addr_str):
>         if name in ['Name', 'Address', 'Phone' ]:
>             name_loc = string.find(value_str, name)
>             if name_loc != -1:
>                 pair = string.split(value_str[name_loc:], ';',1)
>                 pair1 = string.split(pair[0], ':',1)
>                 setattr(self, name, pair1[1])
>             else:
>                 print"\nname %s NOT found" % name
>                 raw_input("\nPAUSED")
>###
>
>It's not really an adding: it's more like a renaming of your __setattr__()
>definition.  *grin* In many cases, we want to avoid the magical nature of
>__setattr__().  Renaming it to something nonmagical is one way to make the
>code simpler.
>
>
>We can call initFromString() with a simple method call, like this:
>
>###
>s = "Name:Mr Smith;Address:123 Main St;Phone:408-123-4567;"
>address = Address()
>address.initFromString('Name', s)
>address.initFromString('Address', s)
>address.initFromString('Phone', s)
>###
>
>
>Once we have this, we might notice that we may want to initialize all of
>the values in our attribute from the string at once.  So the code
>reorganization allows us to consider if something like:
>
>###
>s = "Name:Mr Smith;Address:123 Main St;Phone:408-123-4567;"
>address = Address()
>address.initAllFromString(s)      ## maybe something like this is a good
>                                   ## idea... ?
>###
>
>so that you may not need to explicitely name the attributes that you'd
>like to set.  If you knew all the attributes in advance, there wouldn't be
>a point to read them dynamically, since we'd be able to do something like:
>
>     address.Name = lookupValueInString('Name', s)
>     address.Address = lookupValueinString('Address', s)
>     ...
>
>which would be easier for a person to read and understand.
>
>
>Modifying __setattr__() can often unnecessarily complicate the definition
>of a class, because it introduces an intrusive change to the way we
>initialize our object's attributes.  Unless we're doing something really
>special, we may find it's a good idea to avoid redefining __setattr__()
>in Python.
>
>
>By the way, Jeff Shannon correctly pointed out that, in most cases, we
>also don't have to manually futz with __dict__ to add dynamic attributes.
>
>     http://mail.python.org/pipermail/tutor/2003-April/021815.html
>
>I stand properly chastised.  *grin* It's often a lot simpler to use the
>getattr() and setattr() functions.  So I've subsituted:
>
>                 self.__dict__[name] = pair1[1]
>
>with:
>
>                 setattr(self, name, pair1[1])
>
>so that things look less magical.
>
>
>I hope this helps!