python列表和元组

7-08 13,409

1. 列表和元组简介

跟字符串一样,列表和元组也是序列型的数据类型,可以通过下标或者切片来访问某一个或者某一连续的元素,列表更灵活的是列表和元组可以包含不同类型的对象。列表和元组在很多操作上是一样的,最大的不同是:元组跟字符串一样,是不可变的。这两种数据类型如此相似,那为何有了列表还需要元组呢?因为在某些情况下,使用其中的一种类型要优于另一种。如:(1)你需要把一些敏感数据传递给一个并不了解的函数,你希望你的数据不被这个函数修改,此时当然选元组了。(2)你在处理动态数据时,需要经常更新这个数据结合,此时就应该选列表了。因此,这两种数据类型各有各的用处,它们之间的转换也十分的方便,通过内建函数list()把一个序列类型转换成列表,通过tuple()把一个序列类型转换成元组。

>>> s = u'alexzhou'
>>> list(s)
[u'a', u'l', u'e', u'x', u'z', u'h', u'o', u'u']
>>> tuple(s)
(u'a', u'l', u'e', u'x', u'z', u'h', u'o', u'u')
>>> s = ['alex','zhou']
>>> tuple(s)
('alex', 'zhou')
>>> s = ('alex','zhou')
>>> list(s)
['alex', 'zhou']

2. 列表常用操作

2.1 列表解析
>>> [i for i in range(8)]
[0, 1, 2, 3, 4, 5, 6, 7]
>>> [i+2 for i in range(8)]
[2, 3, 4, 5, 6, 7, 8, 9]

ps:range()函数返回一个列表

2.2 常用内建函数

(1)cmp()

列表之间的比较就是比较列表中的元素,遵循以下规则。

1.如果比较的元素是同类型的,则比较其值,返回结果.
2.如果两个元素不是同一种类型,则检查它们是否是数字.
a. 如果是数字,执行必要的数字强制类型转换,然后比较.
b. 如果有一方的元素是数字,则另一方的元素”大”(数字是”最小的”)
c. 否则,通过类型名字的字母顺序进行比较.
3.如果有一个列表首先到达末尾,则另一个长一点的列表”大”.
4.如果两个列表的所有元素都是相等的,那么返回0,表示两列表大小相等.

>>> l1 = ['a','b']
>>> l2 = ['x','a']
>>> l3 = ['a','b']
>>> l4 = ['x','a','b']
>>> l5 = ['2','x']
>>> cmp(l1,l2)
-1
>>> cmp(l1,l3)
0
>>> cmp(l2,l4)
-1
>>> cmp(l1,l5)
1

(2)max()和min()

>>> s = ['alex','3','zhou']
>>> max(s)
'zhou'
>>> min(s)
'3'

(3)sorted()和reverse()
排序和逆序

>>> s = ['alex','3','zhou']
>>> s.reverse()
>>> s
['zhou', '3', 'alex']
>>> sorted(s)
['3', 'alex', 'zhou']

(4)enumerate()和zip()
enumerate函数可以同时打印index和value,zip函数接受任意多个序列作为参数,将所有序列按相同的索引组合成一个元素是各个序列合并成的元组的新序列,新的序列的长度以参数中最短的序列为准。

>>> sorted(s)
['3', 'alex', 'zhou']
>>> for i,obj in enumerate(s):
...     print i,obj
... 
0 alex
1 3
2 zhou

>>> s = ['alex','3','zhou']
>>> z = ['zhou','4','alex']
>>> zip(s,z)
[('alex', 'zhou'), ('3', '4'), ('zhou', 'alex')]
>>> for i,j in zip(s,z):
...     print i,j
... 
alex zhou
3 4
zhou alex

(5)reduce(function,sequence)和sum(sequence)
reduce函数把列表的前两个元素作为参数传给function,返回计算的结果和列表的下一个元素重新作为function的参数,直到列表的最后一个元素。
sum函数计算列表所有元素的总和,元素必须为数字。

>>> s = ['a','b']
>>> sum(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> s = [1,2]
>>> sum(s)
3
>>> s = [1.5,2]
>>> sum(s)
3.5
>>>def add(x,y):
...     return x+y
>>>reduce(add,range(10))
45
>>>sum(range(5),5)
15

(6)list()和tuple()
list函数和tuple函数把序列通过浅拷贝的方式创建一个列表或元组,常用于列表和元组间的相互转换。

>>> l = [1,2,3]
>>> tuple(l)
(1, 2, 3)
>>> t = (1,2,3)
>>> list(t)
[1, 2, 3]

(7)列表内建函数
list.append(obj)
向列表中添加一个对象

>>> l = [1,2,3]
>>> l.append(4)
>>> l
[1, 2, 3, 4]

list.count(obj)
计算obj在列表中出现的次数

>>> l = [1,1,1,2,2]
>>> l.count(1)
3

list.extend(sequence)
把序列sequence的内容添加到列表

>>> l1 = [1,2]
>>> l2 = [3,4]
>>> l1.extend(l2)
>>> l1
[1, 2, 3, 4]

list.index(obj,i=0,j=len(list))
返回obj在列表中的索引值,如果不存在则抛出ValueError异常

>>> l = [1,2,3,4]
>>> l.index(1)
0
>>> l.index(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.index(x): x not in list

list.insert(index,obj)
在列表的指定索引处插入对象obj,如果index大于列表的长度,则插入到列表最后

>>> l = [1,2,3,4]
>>> l.insert(1,'a')
>>> l
[1, 'a', 2, 3, 4]
>>> l.insert(9,'a')
>>> l
[1, 'a', 2, 3, 4, 'a', 'a']

list.pop(index=-1)
删除并返回列表中指定位置的对象,默认是最后一个元素,若index超出列表长度,则抛出IndexError异常

>>> l = [1,2,3,4]
>>> l.pop()
4
>>> l
[1, 2, 3]
>>> l.pop(0)
1
>>> l
[2, 3]
>>>l.pop(9)
Traceback (most recent call last):
  File "", line 1, in 
IndexError: pop index out of range

list.remove(obj)
从列表中删除对象,若对象不存在则抛出ValueError异常

>>> l = [1,2,3]
>>> l.remove(1)
>>> l
[2, 3]
>>> l.remove('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list

3. 元组常用操作

3.1 元组元素的可变性

元组跟列表的操作很相近,具体操作可以参考以上列表操作,不过由于元组的不可变特效,可以将元组作为字典的key。要注意的是:元组的不可变特效只是对于元组本身而言,如果元组内的元素是可变的对象,是可以改变其值的。

>>> t = ([1,2],3,4)
>>> t[0][0] = 3
>>> t
([3, 2], 3, 4)
>>> t[1] = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
3.2 单元素元组

由于圆括号被重载,单元素元组需要在后面添加一个逗号。

>>> t = (1)
>>> type(t)
<type 'int'>
>>> t = (1,)
>>> type(t)
<type 'tuple'>

4. python对象浅拷贝和深拷贝

浅拷贝是新建一个跟原来类型一样的对象(身份是新的:id(obj)),不过其内容是原来对象元素的引用(内容是旧的),是序列类型对象默认的拷贝方式,
深拷贝则包括对象及其内容都是新的,下面的这些操作是浅拷贝。

(1)完全切片操作[:]
(2)利用工厂函数,比如 list(),dict()等
(3)使用 copy 模块的 copy 函数

下面通过一个例子来说明浅拷贝和深拷贝
4.1 创建一个列表,并采用上面三种方式进行浅拷贝

>>> user = ['user_id',['username','alexzhou']]
>>> alex = user[:]
>>> zhou = list(user)
>>> import copy
>>> hai = copy.copy(user)
>>> [id(x) for x in user,alex,zhou,hai]
[140325195435976, 140325195478368, 140325195480528, 140325195480600]

从上面可以看出,各个对象的id是不一样的
4.2 尝试改变各列表的值,看看会发生什么事

>>> alex[0] = '1'
>>> zhou[0] = '2'
>>> hai[0] = '3'
>>> user,alex,zhou,hai
(['user_id', ['username', 'alexzhou']], ['1', ['username', 'alexzhou']], ['2', ['username', 'alexzhou']], ['3', ['username', 'alexzhou']])
>>> alex[1][1] = 'test'
>>> user,alex,zhou,hai
(['user_id', ['username', 'test']], ['1', ['username', 'test']], ['2', ['username', 'test']], ['3', ['username', 'test']])
>>> [id(x) for x in alex]
[140325295415488, 140325195435400]
>>> [id(x) for x in zhou]
[140325295406992, 140325195435400]
>>> [id(x) for x in hai]
[140325195481664, 140325195435400]

从测试结果可以看出,非容器类型(数字、字符串等)没有发生拷贝操作,各列表中的user_id互不影响,id也不一样;改变了alex中列表的值,其它对象中列表的值也受到了影响,并且id的值是一样的,表明各对象中列表的内容都是指向同一对象的,所以发生了浅拷贝操作。
4.3 进行深拷贝操作

>>> jiang = copy.deepcopy(user)
>>> jiang
['user_id', ['username', 'test']]
>>> [id(x) for x in jiang]
[140325195467488, 140325195480456]
>>> alex[1][1] = 'alex'
>>> alex,zhou,hai,jiang
(['1', ['username', 'alex']], ['2', ['username', 'alex']], ['3', ['username', 'alex']], ['user_id', ['username', 'test']])

可以看到对象jiang的id跟其它浅拷贝对象是不一样的,改变对象alex列表中元素的值对jiang对象没有任何影响。注意:如果对象是不可变类型,如元组或者数字、字符串等,那么对它进行深拷贝也只能得到浅拷贝对象。

>>> user1 = ['user_id',('username','alex')]
>>> user2 = copy.deepcopy(user1)
>>> [id(x) for x in user1,user2]
[140325195477936, 140325195480168]
>>> [id(x) for x in user1]
[140325195467488, 140325195435112]
>>> [id(x) for x in user2]
[140325195467488, 140325195435112]
由于元组本身是不可变的,可以看到进行深拷贝后user1对象和user2对象中的元组id是一样的,本质上只进行了浅拷贝。

lua面向对象模拟简介

lua不是面向对象语言,但可以通过表(table)和元表(metatable)来模拟。table 是 lua 中唯一的一种数据结构,它可以用来描述原始的数组、符号表、集合、 记录、...

阅读全文

在c/c++中调用lua函数

上篇文章完成了在lua中调用c/c++函数,现在来实现在c/c++中调用lua函数。 首先完成lua代码,创建sum.lua: function add(x, y) return x + y; end 为了...

阅读全文

在lua中调用c/c++函数

lua是一种轻量级的脚本语言,用来扩展c和c++非常好,在游戏开发中使用很普遍。 首先下载lua,因为我是在win7下,所以我这里下载了luaforwindows,安装到F:\Lu...

阅读全文

2 条评论

  1. 能不能有方法让List里面的每个数都加上或者乘上一个数,比如:a=[1,2,3],可以很便捷地变成[11,12,13]

    1. 当然可以的阿,可以参考2.1 列表解析

      a = [1,2,3]
      [i+10 for i in a]
      [11, 12, 13]
      

欢迎留言