question on namedtuple

Peter Otten __peter__ at web.de
Thu Apr 1 16:36:09 EDT 2010


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



More information about the Python-list mailing list