What are “named tuples” in Python?

前端 未结 11 2085
名媛妹妹
名媛妹妹 2020-11-22 06:58

Reading the changes in Python 3.1, I found something... unexpected:

The sys.version_info tuple is now a named tuple:

相关标签:
11条回答
  • 2020-11-22 07:31

    namedtuple

    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
    

    When might you use namedtuple

    1. As just stated, the namedtuple makes understanding tuples much easier. So if you need to reference the items in the tuple, then creating them as namedtuples just makes sense.
    2. Besides being more lightweight than a dictionary, namedtuple also keeps the order unlike the dictionary.
    3. As in the example above, it is simpler to create an instance of namedtuple than dictionary. And referencing the item in the named tuple looks cleaner than a dictionary. p.hue rather than p['hue'].

    The syntax

    collections.namedtuple(typename, field_names[, verbose=False][, rename=False])
    
    • namedtuple is in the collections library.
    • typename: This is the name of the new tuple subclass.
    • field_names: A sequence of names for each field. It can be a sequence as in a list ['x', 'y', 'z'] or string x y z (without commas, just whitespace) or x, y, z.
    • rename: If rename is 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'.
    • verbose: If verbose is 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.

    Methods

    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

    0 讨论(0)
  • 2020-11-22 07:31

    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)
    
    0 讨论(0)
  • 2020-11-22 07:35

    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)
    
    0 讨论(0)
  • 2020-11-22 07:37

    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)
    
    0 讨论(0)
  • 2020-11-22 07:37

    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.

    0 讨论(0)
提交回复
热议问题