What are “named tuples” in Python?

前端 未结 11 2086
名媛妹妹
名媛妹妹 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 "", line 1, in 
        File "", 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

提交回复
热议问题