question on namedtuple

Discussion in 'Python' started by hetchkay, Apr 1, 2010.

  1. hetchkay

    hetchkay Guest

    Hi,
    For purposes I don't want to go into here, I have the following code:
    def handleObj(obj):
    if isinstance(obj, MyType):
    return obj.handle()
    elif isinstance(obj, (list, tuple, set)):
    return obj.__class__(map (handleObj, obj))
    elif isinstance(obj, dict):
    return obj.__class__((handleObj(k), handleObj(v)) for k, v in
    obj.items())
    else:
    return obj

    This works fine except if obj is a namedtuple. A namedtuple object has
    different constructor signature from tuple:
    >>> tuple([1,2])

    (1,2)
    >>> collections.namedtuple("sample", "a, b")([1, 2])

    Traceback (most recent call last):
    File "CommandConsole", line 1, in <module>
    TypeError: __new__() takes exactly 3 arguments (2 given)
    >>> collections.namedtuple("sample", "a, b")(1, 2)

    sample(a=1, b=2)

    Is there any easy way of knowing that the obj is a namedtuple and not
    a plain tuple [so that I could use obj.__class__(*map(handleObj, obj))
    instead of obj.__class__(map(handleObj, obj)) ].

    Thanks in advance for your help.

    Krishnan
     
    hetchkay, Apr 1, 2010
    #1
    1. Advertising

  2. hetchkay

    Chris Rebert Guest

    On Thu, Apr 1, 2010 at 11:35 AM, hetchkay <> wrote:
    > Hi,
    > For purposes I don't want to go into here, I have the following code:
    > def handleObj(obj):
    >  if isinstance(obj, MyType):
    >     return obj.handle()
    >  elif isinstance(obj, (list, tuple, set)):
    >     return obj.__class__(map (handleObj, obj))
    >  elif isinstance(obj, dict):
    >     return obj.__class__((handleObj(k), handleObj(v)) for k, v in
    > obj.items())
    >  else:
    >     return obj
    >
    > This works fine except if obj is a namedtuple. A namedtuple object has
    > different constructor signature from tuple:
    >>>> tuple([1,2])

    > (1,2)
    >>>> collections.namedtuple("sample", "a, b")([1, 2])

    > Traceback (most recent call last):
    >  File "CommandConsole", line 1, in <module>
    > TypeError: __new__() takes exactly 3 arguments (2 given)
    >>>> collections.namedtuple("sample", "a, b")(1, 2)

    > sample(a=1, b=2)
    >
    > Is there any easy way of knowing that the obj is a namedtuple and not
    > a plain tuple [so that I could use obj.__class__(*map(handleObj, obj))
    > instead of obj.__class__(map(handleObj, obj)) ].


    It's very slightly brittle, but a good heuristic is probably:

    if isinstance(obj, tuple) and all(hasattr(obj, attr_name) for \
    attr_name in ('_make','_fields','_replace','_asdict')):
    return obj.__class__(*map(handleObj, obj))

    I couldn't find/think of a more direct/reliable method. Though perhaps
    there's some more obscure but accurate method.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Apr 1, 2010
    #2
    1. Advertising

  3. hetchkay

    Peter Otten Guest

    hetchkay wrote:

    > For purposes I don't want to go into here, I have the following code:
    > def handleObj(obj):
    > if isinstance(obj, MyType):
    > return obj.handle()
    > elif isinstance(obj, (list, tuple, set)):
    > return obj.__class__(map (handleObj, obj))
    > elif isinstance(obj, dict):
    > return obj.__class__((handleObj(k), handleObj(v)) for k, v in
    > obj.items())
    > else:
    > return obj
    >
    > This works fine except if obj is a namedtuple. A namedtuple object has
    > different constructor signature from tuple:
    >>>> tuple([1,2])

    > (1,2)
    >>>> collections.namedtuple("sample", "a, b")([1, 2])

    > Traceback (most recent call last):
    > File "CommandConsole", line 1, in <module>
    > TypeError: __new__() takes exactly 3 arguments (2 given)
    >>>> collections.namedtuple("sample", "a, b")(1, 2)

    > sample(a=1, b=2)
    >
    > Is there any easy way of knowing that the obj is a namedtuple and not
    > a plain tuple [so that I could use obj.__class__(*map(handleObj, obj))
    > instead of obj.__class__(map(handleObj, obj)) ].


    I don't think there is a safe way to do this short of a comprehensive list
    of namedtuple classes. In practice it may be sufficient to check the duck
    type of the tuple subclass, e. g.:

    elif isinstance(obj, (list, set)):
    return obj.__class__(map(handleObj, obj))
    elif isinstance(obj, tuple):
    try:
    make = obj._make
    except AttributeError:
    make = obj.__class__
    return make(handleObj(item) for item in obj)

    Peter
     
    Peter Otten, Apr 1, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason R. Coombs

    namedtuple suggestions

    Jason R. Coombs, Jun 13, 2008, in forum: Python
    Replies:
    1
    Views:
    305
    Calvin Spealman
    Jun 13, 2008
  2. David A. Barrett

    collections.namedtuple: conflicting instances?

    David A. Barrett, Sep 23, 2010, in forum: Python
    Replies:
    0
    Views:
    245
    David A. Barrett
    Sep 23, 2010
  3. Chris Rebert
    Replies:
    1
    Views:
    337
  4. Replies:
    9
    Views:
    172
    Tim Chase
    Sep 26, 2013
  5. Virendra Tripathi

    Re: Convert namedtuple to dictionary

    Virendra Tripathi, Sep 26, 2013, in forum: Python
    Replies:
    0
    Views:
    116
    Virendra Tripathi
    Sep 26, 2013
Loading...

Share This Page