Reading the changes in Python 3.1, I found something... unexpected:
The sys.version_info tuple is now a named tuple:
is one of the easiest ways to clean up your code and make it more readable. It self-documents what is happening in the tuple. Namedtuples instances are just as memory efficient as regular tuples as they do not have per-instance dictionaries, making them faster than dictionaries.
from collections import namedtuple
Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
p = Color(170, 0.1, 0.6)
if p.saturation >= 0.5:
print "Whew, that is bright!"
if p.luminosity >= 0.5:
print "Wow, that is light"
Without naming each element in the tuple, it would read like this:
p = (170, 0.1, 0.6)
if p[1] >= 0.5:
print "Whew, that is bright!"
if p[2]>= 0.5:
print "Wow, that is light"
It is so much harder to understand what is going on in the first example. With a namedtuple, each field has a name. And you access it by name rather than position or index. Instead of p[1]
, we can call it p.saturation. It's easier to understand. And it looks cleaner.
Creating an instance of the namedtuple is easier than creating a dictionary.
# dictionary
>>>p = dict(hue = 170, saturation = 0.1, luminosity = 0.6)
>>>p['hue']
170
#nametuple
>>>from collections import namedtuple
>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)
>>>p.hue
170
p.hue
rather than
p['hue']
.The syntax
collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
['x', 'y', 'z']
or string x y z
(without commas, just
whitespace) or x, y, z
.True
, invalid fieldnames are automatically
replaced with positional names. For example, ['abc', 'def', 'ghi','abc']
is converted to ['abc', '_1', 'ghi', '_3']
, eliminating the
keyword 'def'
(since that is a reserved word for defining functions)
and the duplicate fieldname 'abc'
.True
, the class definition is printed just
before being built.You can still access namedtuples by their position, if you so choose. p[1] == p.saturation
. It still unpacks like a regular tuple.
All the regular tuple methods are supported. Ex: min(), max(), len(), in, not in, concatenation (+), index, slice, etc. And there are a few additional ones for namedtuple. Note: these all start with an underscore. _replace
, _make
, _asdict
.
_replace
Returns a new instance of the named tuple replacing specified fields with new values.
The syntax
somenamedtuple._replace(kwargs)
Example
>>>from collections import namedtuple
>>>Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])
>>>p = Color(170, 0.1, 0.6)
>>>p._replace(hue=87)
Color(87, 0.1, 0.6)
>>>p._replace(hue=87, saturation=0.2)
Color(87, 0.2, 0.6)
Notice: The field names are not in quotes; they are keywords here.
Remember: Tuples are immutable - even if they are namedtuples and have the _replace
method. The _replace
produces a new
instance; it does not modify the original or replace the old value. You can of course save the new result to the variable. p = p._replace(hue=169)
_make
Makes a new instance from an existing sequence or iterable.
The syntax
somenamedtuple._make(iterable)
Example
>>>data = (170, 0.1, 0.6)
>>>Color._make(data)
Color(hue=170, saturation=0.1, luminosity=0.6)
>>>Color._make([170, 0.1, 0.6]) #the list is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)
>>>Color._make((170, 0.1, 0.6)) #the tuple is an iterable
Color(hue=170, saturation=0.1, luminosity=0.6)
>>>Color._make(170, 0.1, 0.6)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 15, in _make
TypeError: 'float' object is not callable
What happened with the last one? The item inside the parenthesis should be the iterable. So a list or tuple inside the parenthesis works, but the sequence of values without enclosing as an iterable returns an error.
_asdict
Returns a new OrderedDict which maps field names to their corresponding values.
The syntax
somenamedtuple._asdict()
Example
>>>p._asdict()
OrderedDict([('hue', 169), ('saturation', 0.1), ('luminosity', 0.6)])
Reference: https://www.reddit.com/r/Python/comments/38ee9d/intro_to_namedtuple/
There is also named list which is similar to named tuple but mutable https://pypi.python.org/pypi/namedlist
Another way (a new way) to use named tuple is using NamedTuple from typing package: Type hints in namedtuple
Let's use the example of the top answer in this post to see how to use it.
(1) Before using the named tuple, the code is like this:
pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)
from math import sqrt
line_length = sqrt((pt1[0]-pt2[0])**2 + (pt1[1]-pt2[1])**2)
print(line_length)
(2) Now we use the named tuple
from typing import NamedTuple, Number
inherit the NamedTuple class and define the variable name in the new class. test is the name of the class.
class test(NamedTuple):
x: Number
y: Number
create instances from the class and assign values to them
pt1 = test(1.0, 5.0) # x is 1.0, and y is 5.0. The order matters
pt2 = test(2.5, 1.5)
use the variables from the instances to calculate
line_length = sqrt((pt1.x-pt2.x)**2 + (pt1.y-pt2.y)**2)
print(line_length)
namedtuple is a factory function for making a tuple class. With that class we can create tuples that are callable by name also.
import collections
#Create a namedtuple class with names "a" "b" "c"
Row = collections.namedtuple("Row", ["a", "b", "c"])
row = Row(a=1,b=2,c=3) #Make a namedtuple from the Row class we created
print row #Prints: Row(a=1, b=2, c=3)
print row.a #Prints: 1
print row[0] #Prints: 1
row = Row._make([2, 3, 4]) #Make a namedtuple from a list of values
print row #Prints: Row(a=2, b=3, c=4)
What is namedtuple ?
As the name suggests, namedtuple is a tuple with name. In standard tuple, we access the elements using the index, whereas namedtuple allows user to define name for elements. This is very handy especially processing csv (comma separated value) files and working with complex and large dataset, where the code becomes messy with the use of indices (not so pythonic).
How to use them ?
>>>from collections import namedtuple
>>>saleRecord = namedtuple('saleRecord','shopId saleDate salesAmout totalCustomers')
>>>
>>>
>>>#Assign values to a named tuple
>>>shop11=saleRecord(11,'2015-01-01',2300,150)
>>>shop12=saleRecord(shopId=22,saleDate="2015-01-01",saleAmout=1512,totalCustomers=125)
Reading
>>>#Reading as a namedtuple
>>>print("Shop Id =",shop12.shopId)
12
>>>print("Sale Date=",shop12.saleDate)
2015-01-01
>>>print("Sales Amount =",shop12.salesAmount)
1512
>>>print("Total Customers =",shop12.totalCustomers)
125
Interesting Scenario in CSV Processing :
from csv import reader
from collections import namedtuple
saleRecord = namedtuple('saleRecord','shopId saleDate totalSales totalCustomers')
fileHandle = open("salesRecord.csv","r")
csvFieldsList=csv.reader(fileHandle)
for fieldsList in csvFieldsList:
shopRec = saleRecord._make(fieldsList)
overAllSales += shopRec.totalSales;
print("Total Sales of The Retail Chain =",overAllSales)
In Python inside there is a good use of container called a named tuple, it can be used to create a definition of class and has all the features of the original tuple.
Using named tuple will be directly applied to the default class template to generate a simple class, this method allows a lot of code to improve readability and it is also very convenient when defining a class.