python:为什么Tuple操作速度比List快

Dive into python中说道Tuple是不可变的List,一旦创建了一个Tuple,就不能以任何方式改变它。但是Tuple 比 list 操作速度快。如果您定义了一个值的常量集,并且唯一要用它做的是不断地遍历它,请使用 tuple 代替 list。

我写了几行代码测试了一下:

example_list=list()
for i in range(0,500,1):
    example_list.append(i)

example_tuple=tuple(example_list)

start=time.clock()
for item in example_list:
    do something
print " iterate list:",time.clock()-start

start=time.clock()
for item in example_tuple:
   do something
print " iterate tuple:",time.clock()-start

运行结果如下:

iterate list: 9.37050717647e-05
 iterate tuple: 6.8270838e-05

我运行了几次,虽然具体的时间会改变,但是遍历tuple的速度确实比list快。为什么呢?stackoverflow上有人的解释:

http://stackoverflow.com/questions/3340539/why-is-tuple-faster-than-list

大概有以下几个要点:

1、tuple中是不可变的,在CPython中tuple被存储在一块固定连续的内存中,创建tuple的时候只需要一次性分配内存。但是List被的被存储在两块内存中,一块内存固定大小,记录着Python Object(某个list对象)的信息,另一块是不固定大小的内存,用来存储数据。所以,查找时tuple可以快速定位(C中的数组);list必须遍历(C中的链表)。在编译中,由于Tuple是不可变的,python编译器将它存储在它所在的函数或者模块的“常量表”(constants table)中。运行时,只要找到这些预构建的常量元组。但是List是可变的,必须在运行中构建,分配内存。

3、当Tuple的元素是List的时候,它只存储list的引用,(C中定长数组里一个元素是指向某个链表的指针),定位查找时它还是会比List快

4、CPython中已经做了相关优化以减少内存分配次数:释放一个List对象的时候,它的内存会被保存在一个自由List中以重复使用。不过非空list的创建时,仍然需要给它分配内存存储数据。

Tuple 源码

class tuple(object):
    """
    tuple() -> empty tuple
    tuple(iterable) -> tuple initialized from iterable‘s items

    If the argument is a tuple, the return value is the same object.
    """
    def count(self, value): # real signature unknown; restored from __doc__
        """ T.count(value) -> integer -- return number of occurrences of value """
        return 0

    def index(self, value, start=None, stop=None): # real signature unknown; restored from __doc__
        """
        T.index(value, [start, [stop]]) -> integer -- return first index of value.
        Raises ValueError if the value is not present.
        """
        return 0

    def __add__(self, y): # real signature unknown; restored from __doc__
        """ x.__add__(y) <==> x+y """
        pass

    def __contains__(self, y): # real signature unknown; restored from __doc__
        """ x.__contains__(y) <==> y in x """
        pass

    def __eq__(self, y): # real signature unknown; restored from __doc__
        """ x.__eq__(y) <==> x==y """
        pass

    def __getattribute__(self, name): # real signature unknown; restored from __doc__
        """ x.__getattribute__(‘name‘) <==> x.name """
        pass

    def __getitem__(self, y): # real signature unknown; restored from __doc__
        """ x.__getitem__(y) <==> x[y] """
        pass

    def __getnewargs__(self, *args, **kwargs): # real signature unknown
        pass

    def __getslice__(self, i, j): # real signature unknown; restored from __doc__
        """
        x.__getslice__(i, j) <==> x[i:j]

                   Use of negative indices is not supported.
        """
        pass

    def __ge__(self, y): # real signature unknown; restored from __doc__
        """ x.__ge__(y) <==> x>=y """
        pass

    def __gt__(self, y): # real signature unknown; restored from __doc__
        """ x.__gt__(y) <==> x>y """
        pass

    def __hash__(self): # real signature unknown; restored from __doc__
        """ x.__hash__() <==> hash(x) """
        pass

    def __init__(self, seq=()): # known special case of tuple.__init__
        """
        tuple() -> empty tuple
        tuple(iterable) -> tuple initialized from iterable‘s items

        If the argument is a tuple, the return value is the same object.
        # (copied from class doc)
        """
        pass

    def __iter__(self): # real signature unknown; restored from __doc__
        """ x.__iter__() <==> iter(x) """
        pass

    def __len__(self): # real signature unknown; restored from __doc__
        """ x.__len__() <==> len(x) """
        pass

    def __le__(self, y): # real signature unknown; restored from __doc__
        """ x.__le__(y) <==> x<=y """
        pass

    def __lt__(self, y): # real signature unknown; restored from __doc__
        """ x.__lt__(y) <==> x<y """
        pass

    def __mul__(self, n): # real signature unknown; restored from __doc__
        """ x.__mul__(n) <==> x*n """
        pass

    @staticmethod # known case of __new__
    def __new__(S, *more): # real signature unknown; restored from __doc__
        """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
        pass

    def __ne__(self, y): # real signature unknown; restored from __doc__
        """ x.__ne__(y) <==> x!=y """
        pass

    def __repr__(self): # real signature unknown; restored from __doc__
        """ x.__repr__() <==> repr(x) """
        pass

    def __rmul__(self, n): # real signature unknown; restored from __doc__
        """ x.__rmul__(n) <==> n*x """
        pass

    def __sizeof__(self): # real signature unknown; restored from __doc__
        """ T.__sizeof__() -- size of T in memory, in bytes """
        pass

List源码

class list(object):
    """
    list() -> new empty list
    list(iterable) -> new list initialized from iterable‘s items
    """
    def append(self, p_object): # real signature unknown; restored from __doc__
        """ L.append(object) -- append object to end """
        pass

    def count(self, value): # real signature unknown; restored from __doc__
        """ L.count(value) -> integer -- return number of occurrences of value """
        return 0

    def extend(self, iterable): # real signature unknown; restored from __doc__
        """ L.extend(iterable) -- extend list by appending elements from the iterable """
        pass

    def index(self, value, start=None, stop=None): # real signature unknown; restored from __doc__
        """
        L.index(value, [start, [stop]]) -> integer -- return first index of value.
        Raises ValueError if the value is not present.
        """
        return 0

    def insert(self, index, p_object): # real signature unknown; restored from __doc__
        """ L.insert(index, object) -- insert object before index """
        pass

    def pop(self, index=None): # real signature unknown; restored from __doc__
        """
        L.pop([index]) -> item -- remove and return item at index (default last).
        Raises IndexError if list is empty or index is out of range.
        """
        pass

    def remove(self, value): # real signature unknown; restored from __doc__
        """
        L.remove(value) -- remove first occurrence of value.
        Raises ValueError if the value is not present.
        """
        pass

    def reverse(self): # real signature unknown; restored from __doc__
        """ L.reverse() -- reverse *IN PLACE* """
        pass

    def sort(self, cmp=None, key=None, reverse=False): # real signature unknown; restored from __doc__
        """
        L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
        cmp(x, y) -> -1, 0, 1
        """
        pass

    def __add__(self, y): # real signature unknown; restored from __doc__
        """ x.__add__(y) <==> x+y """
        pass

    def __contains__(self, y): # real signature unknown; restored from __doc__
        """ x.__contains__(y) <==> y in x """
        pass

    def __delitem__(self, y): # real signature unknown; restored from __doc__
        """ x.__delitem__(y) <==> del x[y] """
        pass

    def __delslice__(self, i, j): # real signature unknown; restored from __doc__
        """
        x.__delslice__(i, j) <==> del x[i:j]

                   Use of negative indices is not supported.
        """
        pass

    def __eq__(self, y): # real signature unknown; restored from __doc__
        """ x.__eq__(y) <==> x==y """
        pass

    def __getattribute__(self, name): # real signature unknown; restored from __doc__
        """ x.__getattribute__(‘name‘) <==> x.name """
        pass

    def __getitem__(self, y): # real signature unknown; restored from __doc__
        """ x.__getitem__(y) <==> x[y] """
        pass

    def __getslice__(self, i, j): # real signature unknown; restored from __doc__
        """
        x.__getslice__(i, j) <==> x[i:j]

                   Use of negative indices is not supported.
        """
        pass

    def __ge__(self, y): # real signature unknown; restored from __doc__
        """ x.__ge__(y) <==> x>=y """
        pass

    def __gt__(self, y): # real signature unknown; restored from __doc__
        """ x.__gt__(y) <==> x>y """
        pass

    def __iadd__(self, y): # real signature unknown; restored from __doc__
        """ x.__iadd__(y) <==> x+=y """
        pass

    def __imul__(self, y): # real signature unknown; restored from __doc__
        """ x.__imul__(y) <==> x*=y """
        pass

    def __init__(self, seq=()): # known special case of list.__init__
        """
        list() -> new empty list
        list(iterable) -> new list initialized from iterable‘s items
        # (copied from class doc)
        """
        pass

    def __iter__(self): # real signature unknown; restored from __doc__
        """ x.__iter__() <==> iter(x) """
        pass

    def __len__(self): # real signature unknown; restored from __doc__
        """ x.__len__() <==> len(x) """
        pass

    def __le__(self, y): # real signature unknown; restored from __doc__
        """ x.__le__(y) <==> x<=y """
        pass

    def __lt__(self, y): # real signature unknown; restored from __doc__
        """ x.__lt__(y) <==> x<y """
        pass

    def __mul__(self, n): # real signature unknown; restored from __doc__
        """ x.__mul__(n) <==> x*n """
        pass

    @staticmethod # known case of __new__
    def __new__(S, *more): # real signature unknown; restored from __doc__
        """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
        pass

    def __ne__(self, y): # real signature unknown; restored from __doc__
        """ x.__ne__(y) <==> x!=y """
        pass

    def __repr__(self): # real signature unknown; restored from __doc__
        """ x.__repr__() <==> repr(x) """
        pass

    def __reversed__(self): # real signature unknown; restored from __doc__
        """ L.__reversed__() -- return a reverse iterator over the list """
        pass

    def __rmul__(self, n): # real signature unknown; restored from __doc__
        """ x.__rmul__(n) <==> n*x """
        pass

    def __setitem__(self, i, y): # real signature unknown; restored from __doc__
        """ x.__setitem__(i, y) <==> x[i]=y """
        pass

    def __setslice__(self, i, j, y): # real signature unknown; restored from __doc__
        """
        x.__setslice__(i, j, y) <==> x[i:j]=y

                   Use  of negative indices is not supported.
        """
        pass

    def __sizeof__(self): # real signature unknown; restored from __doc__
        """ L.__sizeof__() -- size of L in memory, in bytes """
        pass

    __hash__ = None

List和Tuple相同的用法:

>>> t = ("a", "b", "mpilgrim", "z", "example")
>>> t
(‘a‘, ‘b‘, ‘mpilgrim‘, ‘z‘, ‘example‘)
>>> t[0]
‘a‘
>>> t[-1]
‘example‘
>>> t[1:3]
(‘b‘, ‘mpilgrim‘)

list和tuple定义、索引、分片(slice)方式一样

List和Tuple不同用法:

(1)

>>> t
(‘a‘, ‘b‘, ‘mpilgrim‘, ‘z‘, ‘example‘)
>>> t.append("new")
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: ‘tuple‘ object has no attribute ‘append‘
>>> t.remove("z")
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: ‘tuple‘ object has no attribute ‘remove‘
>>> t.index("example")
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: ‘tuple‘ object has no attribute ‘index‘
>>> "z" in t
True

从源码也可以看出,tuple中没有append\extend\remove\pop\index等用法。但是可以使用 in 来查看一个元素是否存在于 tuple 中。

(2)

d=dict()
d[example_tuple]="a"
d[example_list]="b"

Traceback (most recent call last):  File "N:/WorkSpace/python-workspace/tuple_test.py", line 15, in <module>    d[example_list]="b"TypeError: unhashable type: ‘list‘
tuple2=([2,3,4,5],[1,2,4,5])d=dict()d[tuple2]="a"

Traceback (most recent call last):  File "N:/WorkSpace/python-workspace/tuple_test.py", line 14, in <module>    d[tuple2]="a"TypeError: unhashable type: ‘list‘

Tuples 可以在 dictionary 中被用做 key,但是 list 不行。实际上,事情要比这更复杂。Dictionary key 必须是不可变的。Tuple 本身是不可改变的,但是如果您有一个 list 的 tuple,那就认为是可变的了,用做 dictionary key 就是不安全的。只有字符串、整数或其它对 dictionary 安全的 tuple 才可以用作 dictionary key。

Tuple和List相互转换:

example_list=list()
for i in range(0,10,1):
    example_list.append(i)

example_tuple=tuple(example_list)
example_list2=list(example_tuple)
print "tuple",example_tuple
print "list",example_list2

运行结果:

tuple (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

内置的 tuple 函数接收一个 list,并返回一个有着相同元素的 tuple。而 list 函数接收一个 tuple 返回一个 list。

时间: 2024-08-01 23:41:40

python:为什么Tuple操作速度比List快的相关文章

Python字典增删操作技巧简述

Python编程语言是一款比较容易学习的计算机通用型语言.对于初学者来说,首先需要掌握的就是其中的一些基础应用.比如今天我们为大家介绍的Python字典的相关操作,就是我们在学习过程中需要熟练掌握的技巧. Python字典(Dictionary)是一种映射结构的数据类型,由无序的“键-值对”组成.字典的键必须是不可改变的类型,如:字符串,数字,tuple:值可以为任何Python数据类型. 1.新建Python字典 >>> dict = {} #新建一个空字典 >>>

python学习之操作mysql

欢迎点击个人博客 http://www.iwangzheng.com/ 刚开始学python,所以很多代码都需要在ipython里尝试一下.今天记录的是最基本的操作mysql数据库. 写数据库连接操作的时候,仿佛回到了当年在前两家公司写asp.net的感觉. 1.首先在mysql数据库里新建个数据库 create database db_02 default charset utf8; create table user (id int auto_increment primary key,us

Python 列表(list)操作

创建列表 sample_list = ['a',1,('a','b')] Python 列表操作 sample_list = ['a','b',0,1,3] 得到列表中的某一个值 value_start = sample_list[0] end_value = sample_list[-1] 删除列表的第一个值 del sample_list[0] 在列表中插入一个值 sample_list[0:0] = ['sample value'] 得到列表的长度 list_length = len(sa

python基本图像操作

Python基本图像操作 使用python进行基本的图像操作与处理 前言: 与早期计算机视觉领域多数程序都是由 C/C++ 写就的情形不同.随着计算机硬件速度越来越快,研究者在考虑选择实现算法语言的时候会更多地考虑编写代码的效率和易用性,而不是像早年那样把算法的执行效率放在首位.这直接导致近年来越来越多的研究者选择 Python 来实现算法. 今天在计算机视觉领域,越来越多的研究者使用 Python 开展研究,所以有必要去学习一下十分易用的python在图像处理领域的使用,这篇博客将会介绍如何使

计算器、tuple操作、dict、其他常用操作

计算器 #!/usr/bin/env python #!--coding:utf-8 -- #!shenjie :2018/1/23 22:34 #[email protected] :shenjie #[email protected]: 计算器.py def add(string): total=0 numbers=[] numbers+=string.split('+') for num in numbers: total+=int(num.strip()) print('{0}={1}'

python通过openpyxl操作excel

python 对Excel操作常用的主要有xlwt.xlrd.openpyxl ,前者xlwt主要适合于对后缀为xls比较进行写入,而openpyxl主要是针对于Excel 2007 以上版本进行操作,也就是对后缀为xlsx进行操作. Excel 主要有三大元素,工作簿,Sheet 页,单元格,一个工作簿可以包含多个Sheet页面,而Sheet页由N多个单元格组成,而单元格主要用来存储数据: 一.安装插件 pip install openpyxl 二.创建Excel文件 操作excel之前,首先

用 Psyco 让 Python 运行得像 C 一样快

https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-28/ Python 对于您想让它做的事来说通常够快了.编程新手对于类似 Python 这样的解释型/字节编译型语言,将 90% 的关注点集中在执行速度方面,是相当幼稚的.在最新的硬件上,大多数非优化的 Python 程序运行的速度和所需要达到的速度一样快,而且,花费额外的编程工作以使应用程序运行得更快实在没什么意义. 因此,在本文,我只对其它的百分之十感兴趣.有时,Pyth

Python list &tuple

1        List和Tuple 1.1   List(有序可重复可修改) list是一种有序的集合,可以随时添加和删除其中的元素. >>> list=[1,2,3] >>> list [1, 2, 3] >>> list=['1','2','3'] >>> list ['1', '2', '3'] >>> len(list)     --显示list中的元素个数 3 >>>list[0]  

Python中tuple的使用

Tuple 是不可变 list. 一旦创建了一个 tuple 就不能以任何方式改变它. 定义 tuple >>> t = ("a", "b", "mpilgrim", "z", "example")  >>> t ('a', 'b', 'mpilgrim', 'z', 'example') >>> t[0]