在写一些比较小的类的时候,例如 Point(x, y) ,不用去定义一个类Point
class Point: def __init__(self, x=1.0, y=1.0): self.x = x self.y = y
可使用namedtuple替换:
Point = namedtuple('Point', ['x', 'y'], defaults=[1.0, 1.0])
假设有一个列表points,它是一系列点的集合
points = [Point() for _ in range(100000)]
此时使用namedtuple可减少内存开销(Named tuple instances do not have per-instance dictionaries, so they are lightweight and require no more memory than regular tuples.)
也可使用__slots__来限制属性和方法,减少内存开销
class Point: __slots__ = x, y def __init__(self, x=1.0, y=1.0): self.x = x self.y = y
也可使用dataclass
from dataclasses import dataclass @dataclass class Point: x: float = 1.0 y: float = 1.0
示例:
设置默认值
from collections import namedtuple
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0]) >>> Account._field_defaults {'balance': 0}
>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0,0]) >>> Account._field_defaults
{'type': 0, 'balance': 0}
csv、sqlite
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade') import csv for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))): print(emp.name, emp.title) import sqlite3 conn = sqlite3.connect('/companydata') cursor = conn.cursor() cursor.execute('SELECT name, age, title, department, paygrade FROM employees') for emp in map(EmployeeRecord._make, cursor.fetchall()): print(emp.name, emp.title)
方法
>>> t = [11, 22] >>> Point._make(t) Point(x=11, y=22) >>> p = Point(x=11, y=22) >>> p._asdict() OrderedDict([('x', 11), ('y', 22)]) >>> p = Point(x=11, y=22) >>> p._replace(x=33) Point(x=33, y=22) >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now()) >>> p._fields # view the field names ('x', 'y') >>> Color = namedtuple('Color', 'red green blue') >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields) >>> Pixel(11, 22, 128, 255, 0) Pixel(x=11, y=22, red=128, green=255, blue=0) >>> getattr(p, 'x') 11 >>> class Point(namedtuple('Point', ['x', 'y'])): ... __slots__ = () ... @property ... def hypot(self): ... return (self.x ** 2 + self.y ** 2) ** 0.5 ... def __str__(self): ... return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot) >>> for p in Point(3, 4), Point(14, 5/7): ... print(p) Point: x= 3.000 y= 4.000 hypot= 5.000 Point: x=14.000 y= 0.714 hypot=14.018 >>> Point3D = namedtuple('Point3D', Point._fields + ('z',)) >>> Book = namedtuple('Book', ['id', 'title', 'authors']) >>> Book.__doc__ += ': Hardcover book in active collection' >>> Book.id.__doc__ = '13-digit ISBN' >>> Book.title.__doc__ = 'Title of first printing' >>> Book.authors.__doc__ = 'List of authors sorted by last name' >>> Account = namedtuple('Account', 'owner balance transaction_count') >>> default_account = Account('<owner name>', 0.0, 0) >>> johns_account = default_account._replace(owner='John') >>> janes_account = default_account._replace(owner='Jane')
参考链接