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