18 mapping names to sequence elements

Posted by FlyingIsFun1217 on Thu, 17 Feb 2022 08:34:08 +0100

problem

You have a piece of code that accesses elements in lists or tuples through subscripts, but this sometimes makes your code difficult to read, so you want to access elements by name.

Solution

​ collection. The namedtuple () function helps you solve this problem by using an ordinary tuple object. This function is actually a factory method that returns standard subclasses in python. You need to pass the type name and the fields you need to it, and then it returns a class. You can initialize this class and pass values for the fields you define. Code example:

from collections import namedtuple
Subscriber=namedtuple('Subscriber',['addr','joined'])
sub=Subscriber('jonesy@example.com','2021-10-19')
print(sub) # ->Subscriber(addr='jonesy@example.com', joined='2021-10-19')
print(sub.addr)   # ->jonesy@example.com
print(sub.joined) # ->2021-10-19

Although the instance of namedtuple looks like an ordinary class instance, it is interchangeable with tuple types and supports all ordinary tuple operations, such as indexing and decompression. For example:

print(len(sub))  # ->2
addr, joined = sub
print(addr)  # ->jonesy@example.com
print(joined)  # ->2021-10-19

One of the main uses of named tuples is to free your code from subscript operations. Therefore, if you return a large list of tuples from the database call and manipulate the elements through subscripts, your code may make mistakes when you add new columns to the table. But if you use named tuples, you won't have such concerns.

For clarity, the following code uses ordinary tuples:

def computer_cost(records):
    total=0.0
    for rec in records:
        total+=rec[1]*rec[2]
    return total

Subscript operation usually makes the code unclear and relies heavily on the organization of records. The following is the version using named tuples:

def computer_cost(records):
    total = 0.0
    for rec in records:
        s = Stock(*rec)
        total += s.shares * s.price
    return total

discuss

Another use of named tuples is as an alternative to dictionaries, because dictionaries need more space to store. If you need to build a very large data structure containing a dictionary, it is more efficient to use named tuples. However, it should be noted that, unlike dictionaries, a named tuple is immutable. For example:

s=Stock(name='ACME',shares=100,price=123.45)
s.shares=75 #  AttributeError: can't set attribute

If you really need to change the value of the attribute, you can use the named tuple instance_ Replace () method, which will create a new named tuple and create the corresponding field to replace with a new value, such as:

s=s._replace(shares=75)
print(s)  # ->Stock(name='ACME', shares=75, price=123.45)

​ _ Another useful feature of the replace() method is that when your named tuple has optional or missing fields, it is a very convenient method to fill in data. You can first create a prototype tuple containing default values and then use it_ The replace() method creates a new instance whose value has been updated. For example:

Stock = namedtuple('Stock', ['name', 'shares', 'price', 'date', 'time'])
stock_prototype = Stock('', 0, 0.0, None, None)


def dict_to_stock(s):
    return stock_prototype._replace(**s)

Here is how to use it:

a = {'name': 'ACME', 'shares': 100, 'price': 123.45}
dict_to_stock(a)
print(dict_to_stock(a))  # ->Stock(name='ACME', shares=100, price=123.45, date=None, time=None)
b={'name': 'ACME', 'shares': 100, 'price': 123.45,'date':'2022/02/16'}
print(dict_to_stock(b)) # ->Stock(name='ACME', shares=100, price=123.45, date='2022/02/16', time=None)

Finally, if your goal is to define an efficient data structure that needs to update many instance properties, naming tuples is not your best choice. At this point, you should consider defining an inclusion__ slots__ Method.

Topics: Python