32

I create a named tuple like this:

from collections import namedtuple
spam = namedtuple('eggs', 'x, y, z')
ham = spam(1,2,3)

Then I can access elements of ham with e.g.

>>> ham.x
1
>>> ham.z
3

In the interpreter,

>>> ham
eggs(x=1, y=2, z=3)

But what if I just want to get 'eggs'? The only way I've been able to think of is

>>> ham.__repr__.split('(')[0]
'eggs'

but this seems a bit messy. Is there a cleaner way of doing it?

Why do named tuples have this 'eggs' aspect to them if it isn't possible to access it without resorting to a private method?

aaren
  • 5,325
  • 6
  • 29
  • 24

4 Answers4

36

You can get the __name__ attribute of the class:

>>> type(ham).__name__
'eggs'

(Here using the type() builtin to get the class).

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • 1
    This is better, but still resorting to a private method. Why have the 'eggs' part at all if it isn't an attribute of the ham object? – aaren Jun 07 '12 at 21:05
  • 2
    @aaren It's not a private method - double underscores both sides show that the method - or, in this case, attribute is special to how Python works. It makes no sense to give the name to the ham object because it isn't part of the ham object. It's part of the class. Anything that is of the class' scope is stored in the class, as makes sense. The name of the class is needed - as you are not using a `class` statement, you must give the name to python explicitly. – Gareth Latty Jun 07 '12 at 21:08
  • @aaren It's not attribute of the ham object, but it's an attribute of its class (which is in turn an attribute of the object). Also note that neither of those is neither private nor a method - both are public attributes, though using *double* underscores to indicate magic and to avoid clashing with user-defined names. –  Jun 07 '12 at 21:08
30

On the topic of namedtuple attributes:

 >>> ham._fields
    ('x', 'y', 'z')

is sometimes useful to know

knowingpark
  • 639
  • 7
  • 16
2

Based on python's doc, namedtuple gives you a new tuple subclass named 'eggs'

So essentially you need the class name

and type(ham).__name__ will give you the class name

xvatar
  • 3,229
  • 17
  • 20
1
>>> ham.__class__.__name__
'eggs'
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • 3
    -1. Don't access the `__class__` attribute directly, it's bad practice. The `type()` builtin is there for a reason. – Gareth Latty Jun 07 '12 at 21:01
  • 3
    @Lattyware - It isn't an any worse practice than using `__name__` to access the name. ["Each value is an object, and therefore has a class (also called its type). It is stored as object.__class__."](http://docs.python.org/tutorial/classes.html#random-remarks) – Andrew Clark Jun 07 '12 at 21:03
  • That is different, there is no built-in function to get the name. You wouldn't do `x.__len__()` you'd do `len(x)`. Why do it weirdly here? – Gareth Latty Jun 07 '12 at 21:05
  • I wouldn't call it bad practice, but I consider it ugly and also prefer `type`. As for `__name__`, there is no equivalent builtin so it isn't quite the same. (As an aside, in Python 2 with old-style classes, the two are different, but screw old-style classes, they need to die.) –  Jun 07 '12 at 21:06
  • 3
    @Lattyware - [Because it works with old-style classes as well](http://stackoverflow.com/a/1060547/505154), this may not be relevant to namedtuple for this question, but `obj.__class__` is more portable. – Andrew Clark Jun 07 '12 at 21:08
  • That's just another good reason to avoid old-style classes like the plague. If you care for them, you're doing it wrong and need to get up to speed. If you *have* to care about them because some POS you can't ditch still has them, I'm very sorry for you. But luckily, all *sane* classes are new-style, so unless you have to work with legacy code a lot, there is no reason to care about compatibility with old-style classes. You don't avoid `property` because it does not work with old-style classes, do you? –  Jun 07 '12 at 21:11
  • That's not a good reason to hold back. Many things don't work with old style classes, but we don't avoid using them for that reason. If you are writing new code, use new-style classes and use `type()` for it's job. As you say yourself - `namedtuple`s are guaranteed to be new-style, so it makes even more sense. – Gareth Latty Jun 07 '12 at 21:11
  • I'm not saying that there is anything wrong with `type()`, but I do disagree with `__class__` being bad practice, it is used in various places in Python docs (as well as the top two answers in the duplicate question you linked). – Andrew Clark Jun 07 '12 at 21:19
  • Bad practice might be a strong term, but I'd definitely say ugly. There are plenty of hangovers in the Python docs from when it may have been more suitable to use `__class__` - and I didn't vote those answers up in the duplicate. – Gareth Latty Jun 08 '12 at 00:26