namedtuple

本文探讨了在Python中使用namedtuple、__slots__及dataclass优化小类如Point的内存使用,通过实例展示了如何创建具默认值的Account类,以及在csv、sqlite等场景下使用namedtuple的优势。同时,介绍了namedtuple的多种实用方法,如_make、_asdict、_replace等,以及如何通过继承增强其功能。

在写一些比较小的类的时候,例如 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')

 

 参考链接

namedtuple

dataclass

__slots__

转载于:https://www.cnblogs.com/zzwcng/p/10983446.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值