I am very new to Python, and trying to figure out how to create an object that has values that are accessible either by attribute name, or by index. For example, the way os.stat() returns a stat_result or pwd.getpwnam() returns a struct_passwd.
In trying to figure it out, I've only come across C implementations of the above types. Nothing specifically in Python. What is the Python native way to create this kind of object?
I apologize if this has been widely covered already. In searching for an answer, I must be missing some fundamental concept that is excluding me from finding an answer.
I'm not sure what you're finding hard about this.
A collection accessible by index implements
__getitem__
.A collection accessible by names implements
__getattr__
(or__getattribute__
).You can implement both without any trouble at all. Or, you can use
namedtuple
.To make life simpler, you could extend the
tuple
class so you don't have to implement your own__getitem__
. Or you can define an ordinary class that also has__getitem__
so you didn't have to mess with__getattr__
.For example
Python 2.6 introduced collections.namedtuple to make this easy. With older Python versions you can use the named tuple recipe.
Quoting directly from the docs:
You can't use the same implementation as the result object of os.stat() and others. However Python 2.6 has a new factory function that creates a similar datatype called named tuple. A named tuple is a tuple whose slots can also be addressed by name. The named tuple should not require any more memory, according to the documentation, than a regular tuple, since they don't have a per instance dictionary. The factory function signature is:
The first argument specifies the name of the new type, the second argument is a string (space or comma separated) containing the field names and, finally, if verbose is true, the factory function will also print the class generated.
Example
Suppose you have a tuple containing a username and password. To access the username you get the item at position zero and the password is accessed at position one:
There's nothing wrong with this code but the tuple isn't self-documenting. You have to find and read the documentation about the positioning of the fields in the tuple. This is where named tuple can come to the rescue. We can recode the previous example as follows:
If you are interested of what the code looks like for the newly created Credential-type you can add verbose=True to the argument list when creating the type, in this particular case we get the following output:
The named tuple doesn't only provide access to fields by name but also contains helper functions such as the _make() function which helps creating an Credential instance from a sequence or iterable. For example:
The python library documentation for namedtuple has more information and code examples, so I suggest that you take a peek.