views:

154

answers:

2

How do I check if an object is an instance of a Named tuple?

+3  A: 

Calling the function collections.namedtuple gives you a new type that's a subclass of tuple (and no other classes) with a member named _fields that's a tuple whose items are all strings. So you could check for each and every one of these things:

def isnamedtupleinstance(x):
  t = type(x)
  b = t.__bases__
  if len(b) != 1 or b[0] != tuple: return False
  f = getattr(t, '_fields', None)
  if not isinstance(f, tuple): return False
  return all(type(n)==str for n in f)

it IS possible to get a false positive from this, but only if somebody's going out of their way to make a type that looks a lot like a named tuple but isn't one;-).

Alex Martelli
Correct. I was also wondering why the generated type was not derived from a marker class `NamedTuple` whose definition would simply be `class NamedTuple(tuple): pass` .. just to make it easy for us to check if an object is a namedtuple or not.
Sridhar Ratnakumar
Why should the designers of namedtuple make it typecheckable, Sridhar? Typechecking is generally to be avoided in Python and in this case doesn't tell you anything at all useful—a namedtuple with `x` and `y` fields and one with `cost`, `price`, and `quantity` fields aren't going to be interchangeable. The only level to which they are interchangeable is that they are both tuples.Even in the use case of working with the classes generated by the namedtuple factory, they are just normal classes for good reason and can be used just like a similar hand-made class.
Mike Graham
@Mike: I am writing an extention to named tuples .. which mixin asserts that it is used with a named tuple as its sibling base class. So I only need it for asserting that the mixin is not misused with other types.
Sridhar Ratnakumar
@Srindhar: You don't really need to check that this is an instance of a class generated by namedtuple, you only need it to work with your mixin. A dumb user writing broken code can't be fixed by checks, and a smart user using your code will only be potentially hampered by them. (Also, since `assert`s aren't guaranteed to run, they are not the right tool for checking for something you need to check.)
Mike Graham
@Mike: The mixin does not *require* the check which is only needed for assertion. http://en.wikipedia.org/wiki/Assertion_(computing)#Assertions_in_design_by_contract
Sridhar Ratnakumar
+2  A: 

If you need to check before calling namedtuple specific functions on it, then just call them and catch the exception instead. That's the preferred way to do it in python.

Tor Valamo
My reply to Matthew above explains where I am using this check.
Sridhar Ratnakumar