python---Tuple操作速度比List快

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

example_list=list()

for 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(

运行结果如下:

 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 源码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

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源码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

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(selfcmp=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相同的用法:

1

2

3

4

5

6

7

8

9

>>> 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)

+ View Code

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

(2)

1

2

3

d=dict()

d[example_tuple]="a"

d[example_list]="b"<br><br>Traceback (most recent call last):<br>  File "N:/WorkSpace/python-workspace/tuple_test.py", line 15in <module><br>    d[example_list]="b"<br>TypeError: unhashable type'list'<br><br>

1

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 14in <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相互转换:

1

2

3

4

5

6

7

8

example_list=list()

for 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。

发布了55 篇原创文章 · 获赞 20 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/XTY00/article/details/103869642