[Python-Dev] Py2.6 ideas (original) (raw)
Raymond Hettinger python at rcn.com
Tue Feb 20 07:47:34 CET 2007
- Previous message: [Python-Dev] Py2.6 ideas
- Next message: [Python-Dev] Py2.6 ideas
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Thanks for the comments. Will experiment with them and get back to you..
The alternate naming is fine. At work, we call it ntuple().
The constructor signature has been experimented with several time and had best results in its current form which allows the *args for casting a record set returned by SQL or by the CSV module as in Point(*fetchall(s)), and it allows for direct construction with Point(2,3) without the slower and weirder form: Point((2,3)). Also, the current signature works better with keyword arguments: Point(x=2, y=3) or Point(2, y=3) which wouldn't be common but would be consistent with the relationship between keyword arguments and positional arguments in other parts of the language.
The string form for the named tuple factory was arrived at because it was easier to write, read, and alter than its original form with a list of strings: Contract = namedtuple('Contract stock strike volatility expiration rate iscall') vs. Contract = namedtuple('Contract', 'stock', 'strike', 'volatility', 'expiration', 'rate', 'iscall') That former is easier to edit and to re-arrange. Either form is trivial to convert programmatically to the other and the definition step only occurs once while the use of the new type can appear many times throughout the code. Having experimented with both forms, I've found the string form to be best thought it seems a bit odd. Yet, the decision isn't central to the proposal and is still an open question.
The module idea is nice. Will add it. Likewise with pickling.
The 'show' part of repr was done for speed (localized access versus accessing the enclosing scope. Will rename it to _show to make it clear that it is not part of the API.
Thanks for the accolades and the suggestions.
Raymond
----- Original Message ----- From: "Michele Simionato" <michele.simionato at gmail.com> To: <python-dev at python.org> Sent: Monday, February 19, 2007 9:25 PM Subject: Re: [Python-Dev] Py2.6 ideas
Raymond Hettinger <raymond.hettinger verizon.net> writes:
* Add a pure python namedtuple class to the collections module. I've been using the class for about a year and found that it greatly improves the usability of tuples as records. http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/500261 The implementation of this recipe is really clean and I like it a lot (I even think of including it in our codebase), but there are a few issues that I would like to point out. 1. I find the camelcase confusing and I think that NamedTuple should be spelled namedtuple, since is a function, not a class. The fact that it returns classes does not count ;) 2. I agree with Giovanni Bajo, the constructor signature should be consistent with regular tuples. For instance I want to be able to map a named tuple over a record set as returned by fetchall. 3. I would like to pass the list of the fields as a sequence, not as a string. It would be more consistent and it would make easier the programmatic creation of NamedTuple classes at runtime. 4. I want help(MyNamedTuple) to work well; in particular it should display the right module name. That means that in the m dictionary you should add a module attribute: module = sys.getframe(1).fglobals['name'] 5. The major issue is that pickle does work with named tuples since the module attribute is wrong. The suggestion in #4 would solve even this issue for free. 6. The ability to pass a show function to the repr feems over-engineering to me. In short, here is how I would change the recipe: import sys from operator import itemgetter def namedtuple(f): """Returns a new subclass of tuple with named fields. >>> Point = namedtuple('Point x y'.split()) >>> Point.doc # docstring for the new class 'Point(x, y)' >>> p = Point((11,), y=22) # instantiate with positional args or keywords >>> p[0] + p[1] # works just like the tuple (11, 22) 33 >>> x, y = p # unpacks just like a tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessable by name 33 >>> p # readable repr with name=value style Point(x=11, y=22) """ typename, fieldnames = f[0], f[1:] nargs = len(fieldnames) def new(cls, args=(), **kwds): if kwds: try: args += tuple(kwds[name] for name in fieldnames[len(args):]) except KeyError, name: raise TypeError( '%s missing required argument: %s' % (typename, name)) if len(args) != nargs: raise TypeError( '%s takes exactly %d arguments (%d given)' % (typename, nargs, len(args))) return tuple.new(cls, args) template = '%s(%s)' % ( typename, ', '.join('%s=%%r' % name for name in fieldnames)) def repr(self): return template % self m = dict(vars(tuple)) # pre-lookup superclass methods (for faster lookup) m.update(doc= '%s(%s)' % (typename, ', '.join(fieldnames)), slots = (), # no per-instance dict new = new, repr = repr, module = sys.getframe(1).fglobals['name'], ) m.update((name, property(itemgetter(index))) for index, name in enumerate(fieldnames)) return type(typename, (tuple,), m)
if name == 'main': import doctest TestResults = namedtuple(['TestResults', 'failed', 'attempted']) print TestResults(doctest.testmod())
Python-Dev mailing list Python-Dev at python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/python%40rcn.com
- Previous message: [Python-Dev] Py2.6 ideas
- Next message: [Python-Dev] Py2.6 ideas
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]