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.