[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!