Variable interpolation or indirection for instance attributes

Rich google at moodring.com
Wed Feb 19 10:59:09 EST 2003


Alex,

Thanks. This all looks promising.  Being new to the language I need to
do a bunch more research in order to understand it, but I now know
what to research e.g. __slots__, __dict__,setattr, iteritems, new/old
classes?.  I didn't see much detail on this in my 'Learning Python'
book, which barley mentions setattr and doesn't mention iteritems.
Just noticed it is mentioning Python 1.5.2, so it is a bit dated I
guess.

Not trying to do anything evil or weird ... just a parallel to what I
would do in Perl with:

sub initialize {
  my $self     = shift;    
  my %address  = @_;         

  my @addresskeys   = qw ( Street City State Zip );
  map { $self->{$_} = $address{$_} }  @addresskeys;
}

Looks like you've given me the info, and a lot more to explore ... but
it is all new territory for me and will probably take a little time to
understand more completely.  Maybe the online docs cover this stuff
better than my book .. or is there a book or web resource that you
recommend for further understanding these deeper language and object
elements.

Thanks,
Rich

Alex Martelli <aleaxit at yahoo.com> wrote in message news:<b2vf9s01uu2 at enews2.newsguy.com>...
> Rich wrote:
> 
> > Hello,
> > 
> > New to Python with a Perl background, and I've searched a good bit on
> > this and can't seem to find the answer.  I'd like to know if it is
> > possible to use a variable to hold the name of an instance attribute
> > e.g
> > 
> >      x = 'street'
> > self.x = '123 Albermarle Street'
> > 
> > such that x in self.x gets evaluated to 'street' and thus self.x
> > becomes actually self.street.  I've seen a number of (possibly
> 
> If self's class defines a __setattr__, the second assignment
> gets turned into a call to:
> 
>     self.__setattr__('x', '123 Albermarie Street')
> 
> Now, if this wicked class wants to use parameter 'x' to look
> up the actual name of the attribute to set, nobody can stop it
> from so doing.  Doing the look-up in the variable namespaces
> (see vars(), locals(), globals()) is particularly weird (while
> a look-up into a dictionary you have more control on might be
> perhaps sort of sensible once in a while), but weirdness is not
> _forbidden_ in Python -- just silly, but permitted.
> 
> Note that __setattr__'s code can't just do the setting directly
> or it ends up called recursively; in a new-style class, it can
> (best) delegate up e.g. to object.__setattr__(self, name, value) --
> in an old-style ond, self.__dict__[name]=value is the idiom that
> __setattr__ typically uses to bypass triggering itself.
> 
> > outdated) language proposals about backticks and $ symbols. None of
> > these seem to work including (self.x), $self.x, self.$x, self.x$,
> > `self.x`, etc.  I did see an external library mentioned that had a
> > short perhaps 4 character name begining with an 'i' like 'itrp', but
> > I'm stubbornly thinking that there must be a way within the language
> > to do it.
> 
> The _class_ can be written, within the language, to perform this
> wicked deed.  From _outside_ the class, you can't trick the class
> into making self.x=whatever "black magic" unless the class wants
> to.  (You can of course call setattr(self, x, "blahblah") -- that's
> not black magic and not even silly, indeed quite useful -- but it
> doesn't give you "black magic syntax" and the thrill thereof).
> 
> 
> > At the same time, I'd like to find a way to initialize many class
> > instance attribuites from a passed in dictionary, without just
> > creating a dictionary as a n instance attribute.  And I really want to
> > beat this dead horse to understand whether or not these things are
> > possible, even if there is another way!
> 
> self.__dict__.update(thepassedindictionary)
> 
> should be exactly what you want (for a class that's old-style or
> does not define __slots__).  For more generality (covering slots,
> triggering __setattr__ when need be, and the like), loop:
> 
>     for name, value in thepassedindictionary.iteritems():
>         setattr(self, name, value)
> 
> or, at your discretion, play dirty tricks:
> 
>     map(setattr, self*len(thedict), thedict.keys(), thedict.values())
> 
> I consider the loop immensely preferable, but I know some people
> are heartened by the mere existence of the POSSIBILITY of doing
> things in weird, hard-to-understand ways, so...
> 
> 
> > A more likely example:
> > 
> >  class Address:
> > 
> >   def __init__(self,address=''):
> > 
> >       self.props = ['extended','street','locality','region','postalcode']
> >       self.extended = ''
> >       self.street   = ''
> >       self.locality = ''
> >       self.region   = ''
> > 
> >       if address:
> >         for addresspart in address.keys():
> >           self.(addresspart) = address[addresspart]    # whishful
> > thinking
> >                ^^^^^^^^^^^^^
> >   def __getitem__(self,i):
> >     key = self.props[i]
> >     return eval(self.key)                              # same here
> >                      ^^^^
> 
> Are you sure you want self.postalcode to remain unset by default?  Seems
> strange to me.  I'd code this a bit differently:
> 
> 
> class Address(object):
> 
>   __slots__ = 'extended', 'street', 'locality', 'region', 'postalcode'
> 
>   def __init__(self, address=''):
>     for name in self.__slots__:
>         setattr(self, name, '')
>     for addresspart in address:
>         setattr(self, addresspart, address[addresspart])
> 
>   def __getitem__(self, i):
>     key = self.__slots__[i]
>     return getattr(self, key)
> 
> 
> If I wanted to let Address instances be indexable in such ways (hard
> to see why I should want that), I would probably add a few more
> facilities, such as a __len__ method, and the like.  But anyway,
> I think this does do basically what you want -- plus, it saves some
> overhead in terms of memory for each instance of Address (not a big
> issue, but as long as we're listing the "slots" anyway, we might as
> well do it this way -- AS LONG AS, these are the only attributes
> an Address instance is allowed to have; if you want it to remain
> "expando" instead [in JS terms;-)], just name the class attribute
> to anything not reserved, such as, e.g., "slots" instead of using
> the reserved name "__slots__" which does imply special semantics.
> 
> 
> Alex




More information about the Python-list mailing list