[ python-Feature Requests-1110010 ] 'attrmap' function, attrmap(x)['attname'] == x.attname

SourceForge.net noreply at sourceforge.net
Mon Jun 27 06:18:48 CEST 2005


Feature Requests item #1110010, was opened at 2005-01-26 11:28
Message generated for change (Comment added) made by rhettinger
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1110010&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Library
Group: None
Status: Open
Resolution: None
Priority: 5
Submitted By: Gregory Smith (gregsmith)
Assigned to: Nobody/Anonymous (nobody)
Summary: 'attrmap' function, attrmap(x)['attname'] == x.attname

Initial Comment:
One of the side effects of the new-style classes is that
objects don't necessarily have __dict__ attached to them.
It used to be possible to write things like

   def __str__(self):
          return "Node %(name)s, %(nlinks)d links,
active: %(active)s" % self.__dict__


... but this doesn't work if the class doesn't have a
__dict__. Even if does, I'm not sure it will always get
members from base classes.

There is a 'vars' function; you could put 'vars(self)'
in the above instead of self.__dict__, but it still
doesn't work if
the class doesn't have a __dict__.

I can see different solutions for this:

(1) change the 'string %' operator so that it allows
 %(.name)s, leading to a getattr() on the right-side
argument
  rather than a getitem. 

          return "Node %(.name)s, %(.nlinks)d links,
active: %(.active)s" % self

(2) Make a builtin like vars, but which works when the
object doesn't have a __dict__ I.e. attrmap(x) would
return a mapping which is bound to x, and reading
attrmap(x)['attname'] is the same as
getattr(x,'attname'). Thus

          return "Node %(name)s, %(nlinks)d links,
active: %(active)s" % attrmap(self)


This attrmap() function can be implemented in pure
python, of course.

I originally thought (1) made a lot of sense, but (2) seems
to work just as well and doesn't require changing much.
Also, (1) allows  cases like "%(name)s %(.name2)s",
which are not very useful, but are very likely to be
created by
accident; whereas in (2) you are deciding on the right
of the '%' whether you are naming attributes or
providing mapping keys. 

I'm not sure it's a good idea change 'vars' to have
this behaviour, since vars(x).keys() currently works in
a predictable way when vars(x) works; whereas
attrmap(x).keys() may not be complete, or possible, 
even when attrmap(x) is useful. I.e. when x has a
__getattr__ defined.
On the other hand, vars(x) doesn't currently do much at
all, so maybe it's possible to enhance it like this
without breaking anything.

The motivation for this came from the "%(name)s" issue,
but the attrmap() function would be useful in other
places e.g.

processdata( infile,  outfile, **attrmap(options))

... where options might be obtained from optparse, e.g.
  
Or, an attrmap can be used with the new Templates:
string.Template('Node $name').substitute( attrmap(node))

Both of these examples will work with vars(), but only
when the object actually has __dict__. This is why
I'm thinking it may make sense to enhance vars: some
code may be broken by the change; but other code,
broken by new-style classes, may be unbroken by this
change.

The proxy could be writable, so that
    attrmap(x)['a'] = y
is the same as
     x.a = y
.. which could have more uses.

A possible useful (possibly weird) variation: attrmap
accepts 1 or more parameters, and the resulting
proxy is bound to all of them. when attrmap(x,y,z)['a']
is done, the proxy will try x.a, y.a, z.a until one of
them doesn't raise AttributeError. So it's equivalent
to merging dictionaries. This would be useful
in the %(name)s or Template cases, where you want
information from several objects.





----------------------------------------------------------------------

>Comment By: Raymond Hettinger (rhettinger)
Date: 2005-06-26 23:18

Message:
Logged In: YES 
user_id=80475

-1

While potentially useful, the function is entirely unintuitive (it has 
to be studied a bit before being able to see what it is for).  Also, 
the OP is short on use cases (none were presented).  IMO, this 
belongs as a cookbook recipe.

----------------------------------------------------------------------

Comment By: Josiah Carlson (josiahcarlson)
Date: 2005-06-26 12:47

Message:
Logged In: YES 
user_id=341410

An implementation of the base attrmap functionality (as
suggested by Reinhold in his post in python-dev)...

class attrmap:
    def __init__(self, obj):
        self.obj = obj
    def __getitem__(self, key):
        return getattr(self.obj, key)

To Gregory Smith:  If you merely add the __getitem__ method
with a 'self' as the first argument of getattr, you don't
even need attrmap.

As an aside, when I want dictionary-like behavior from my
classes, I use a dictionary or something that implements a
subset of the mapping protocol.

----------------------------------------------------------------------

Comment By: Martin v. Löwis (loewis)
Date: 2005-02-11 19:51

Message:
Logged In: YES 
user_id=21627

I think I would rather not to see this as a builtin, e.g.
putting it into UserDict.AttrMap instead.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1110010&group_id=5470


More information about the Python-bugs-list mailing list