[Python-ideas] namedtuple baseclass

Steven D'Aprano steve at pearwood.info
Sun Jan 12 12:43:01 CET 2014


On Sun, Jan 12, 2014 at 07:17:56PM +1100, Chris Angelico wrote:
> On Sun, Jan 12, 2014 at 6:53 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
> > So to satisfy this use case, you'd either need an actual namedtuple 
> > base class instead of an abc, or an abc that adds some API for 
> > getting the field names (or name-value pairs). Either of which seems 
> > reasonable--except for the odd quirk of having a public API in a 
> > class that's prefixed with an underscore. (If it's not prefixed with 
> > an underscore, it can conflict with a field name, which defeats the 
> > whole purpose of namedtuple.)
> >
> 
> Is compatibility with the current namedtuple important, or can this be
> done another way? For instance, the fields could be retrieved with
> __getitem__ instead:

It's a tuple. It already uses __getitem__ to return items indexed by 
position. Adding magic so that obj["fields"] is an alias for 
obj._fields is, well, horrible.


> # Hacking it in with a subclass. Gives no benefit
> # but is a proof of concept.
> class Point(namedtuple('Point', ['x', 'y'])):
>     def __getitem__(self, which):
>         if which=="fields": return self._fields
>         return super().__getitem__(which)


I think you missed that namedtuple like objects written in C don't 
have a _fields attribute, e.g. os.stat_result. If you're going to insist 
that they add special handling in __getitem__, wouldn't it just be cleaner and simpler 
to get them to add a _fields attribute?

So... 

* An ABC for namedtuple as agreed by Raymond and Guido wouldn't include 
any extra functionality beyond Sequence, so it doesn't guarantee the 
existence of _fields; that doesn't satisfy the use-case.

* An actual namedtuple superclass only works for the namedtuple factory 
function, not for C namedtuple-like types.

Both could be fixed -- Python could define a namedtuple superclass, and 
all relevant C types like os.stat_result could be changed to inherit 
from them. (But what of those which don't?) Or the ABC could be extended 
to include a promise of _fields, but that would exclude C types. Either 
way, in order to satisfy this use-case, there would be a whole lot of 
changes needed.

Or, you can duck-type:

if isinstance(o, tuple):
    try:
        fields = o._fields
    except AttributeError:
        fields = ...  # fall back


Have I missed something?



-- 
Steven


More information about the Python-ideas mailing list