Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder1.news.weretis.net!feeder.erje.net!eu.feeder.erje.net!xlned.com!feeder7.xlned.com!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; 'api.': 0.04; 'classes.': 0.07; 'interpreted': 0.07; 'mentioned,': 0.07; 'api': 0.09; 'python': 0.09; '*args):': 0.09; '[0,': 0.09; 'args.': 0.09; 'collections': 0.09; 'instance.': 0.09; 'instances.': 0.09; 'length.': 0.09; 'objects.': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'subclass': 0.09; 'subclasses': 0.09; 'terry': 0.09; 'tuple': 0.09; 'typeerror:': 0.09; 'def': 0.10; 'assume': 0.11; '*must*': 0.16; 'created.': 0.16; 'display,': 0.16; 'feature?': 0.16; 'iterable': 0.16; 'iterable,': 0.16; 'length,': 0.16; 'namedtuple': 0.16; 'namedtuples': 0.16; 'presume': 0.16; 'r10': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'reedy': 0.16; 'simplest': 0.16; 'subclasses,': 0.16; 'syntax.': 0.16; 'url:gmane': 0.16; 'written.': 0.16; 'wrote:': 0.17; 'instance': 0.17; 'instance,': 0.17; 'integer': 0.17; 'typical': 0.17; 'url:article': 0.17; 'creates': 0.18; 'jan': 0.18; '>>>': 0.18; 'define': 0.20; 'equivalent': 0.20; 'written': 0.20; 'import': 0.21; 'explicit': 0.22; 'info.': 0.22; 'latter': 0.22; 'produces': 0.22; 'tuples': 0.22; 'example': 0.23; 'raise': 0.24; 'header:In-Reply-To:1': 0.25; 'header:User-Agent:1': 0.26; 'common': 0.26; 'am,': 0.27; 'first,': 0.27; 'implemented': 0.27; 'possibility': 0.27; 'possibly': 0.27; 'question': 0.27; 'replace': 0.27; 'start,': 0.27; 'fixed': 0.28; 'header:X -Complaints-To:1': 0.28; 'actual': 0.28; 'initialized': 0.29; 'obj': 0.29; 'second,': 0.29; 'sensible': 0.29; 'statements': 0.29; 'case,': 0.29; 'skip:_ 10': 0.29; 'class': 0.29; 'returned': 0.30; 'function': 0.30; 'lists': 0.31; 'gets': 0.32; 'url:python': 0.32; 'could': 0.32; 'affects': 0.33; 'instances': 0.33; 'problem': 0.33; 'to:addr:python-list': 0.33; 'that,': 0.34; 'or,': 0.34; 'list': 0.35; 'said,': 0.35; 'so,': 0.35; 'there': 0.35; 'list.': 0.35; 'received:org': 0.36; 'really': 0.36; 'but': 0.36; 'url:org': 0.36; 'should': 0.36; 'bad': 0.37; 'one,': 0.37; 'does': 0.37; 'two': 0.37; 'rather': 0.37; 'subject:: ': 0.38; 'fact': 0.38; 'object': 0.38; 'some': 0.38; 'instead': 0.39; 'to:addr:python.org': 0.39; 'step': 0.39; 'where': 0.40; 'header:Received:5': 0.40; 'think': 0.40; 'your': 0.60; 'john': 0.60; 'range': 0.60; 'first': 0.61; 'between': 0.63; 'different': 0.63; 'ever': 0.63; 'more': 0.63; 'making': 0.64; 'differences': 0.65; 'unnecessary': 0.65; 'fact,': 0.69; 'hoping': 0.72; 'oscar': 0.84; 'received:fios.verizon.net': 0.84; 'reid': 0.84; 'replacements': 0.84; 'stop,': 0.84; 'do:': 0.91; 'mistake': 0.91; 'hand,': 0.97 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Terry Reedy Subject: Re: Differences creating tuples and collections.namedtuples Date: Mon, 18 Feb 2013 16:28:43 -0500 References: <7a40a426-baa9-46f8-8f9d-59ba32b044f3@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: pool-173-75-251-66.phlapa.fios.verizon.net User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130107 Thunderbird/17.0.2 In-Reply-To: <7a40a426-baa9-46f8-8f9d-59ba32b044f3@googlegroups.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 105 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1361222953 news.xs4all.nl 6889 [2001:888:2000:d::a6]:45664 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:39130 On 2/18/2013 6:47 AM, John Reid wrote: > I was hoping namedtuples could be used as replacements for tuples > in all instances. This is a mistake in the following two senses. First, tuple is a class with instances while namedtuple is a class factory that produces classes. (One could think of namedtuple as a metaclass, but it was not implemented that way.) Second, a tuple instance can have any length and different instances can have different lengths. On the other hand, all instances of a particular namedtuple class have a fixed length. This affects their initialization. So does the fact that Oscar mentioned, that fields can be initialized by name. > There seem to be some differences between how tuples and namedtuples > are created. For example with a tuple I can do: > > a=tuple([1,2,3]) But no sensible person would ever do that, since it creates an unnecessary list and is equivalent to a = 1,2,3 The actual api is tuple(iterable). I presume you know that, but it gets to the question you ask about 'why the difference?'. The only reason to use an explicit tuple() call is when you already have an iterable, possibly of unknown length, rather than the individual field objects. In the latter case, one should use a display. > with namedtuples I get a TypeError: > > from collections import namedtuple > B=namedtuple('B', 'x y z') > b=B([1,2,3]) There is no namedtuple B display, so one *must* use an explicit call with the proper number of args. The simplest possibility is B(val0, val1, val2). Initializaing a namedtuple from an iterable is unusual, and hence gets the longer syntax. In other words, the typical use case for a namedtuple class is to replace statements that have tuple display. return a, b, c to return B(a, b, c) or x = a, b, c to x = B(a, b, c) It is much less common to change tuple(iterable) to B(iterable). > def canSequence(obj): > if isinstance(obj, (list, tuple)): > t = type(obj) > return t([can(i) for i in obj]) > else: > return obj The first return could also be written t(map(can, obj)) or, in Python 3, t(can(i) for i in obj). > where obj is a namedtuple and t([can(i) for i in obj]) fails with the TypeError. See http://article.gmane.org/gmane.comp.python.ipython.user/10270 for more info. > > Is this a problem with namedtuples, ipython or just a feature? With canSequence. If isinstance was available and the above were written before list and tuple could be subclassed, canSequence was sensible when written. But as Oscar said, it is now a mistake for canSequence to assume that all subclasses of list and tuple have the same initialization api. In fact, one reason to subclass a class is to change the initialization api. For instance, before python 3, range was a function that returned a list. If lists had always been able to be subclasses, it might instead have been written as a list subclass that attached the start, stop, and step values, like so: # python 3 class rangelist(list): def __init__(self, *args): r = range(*args) self.extend(r) self.start = r.start self.stop = r.stop self.step = r.step r10 = rangelist(10) print(r10, r10.start, r10.stop, r10.step) >>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0 10 1 However, define can() and canSequence(r10) will raise a TypeError, just as with a namedtuple B instance. TypeError: 'list' object cannot be interpreted as an integer So, while your question about the namedtuple api is a legitimate one, your problem with canSequence is not really about namedtuples, but about canSequence making a bad assumption. -- Terry Jan Reedy