python列表、元组详解
2.9. 具名元组(namedtuple)(暂不懂,懒得看) 15
序列是python中最基本的数据结构.序列中的每个元素都分配一个数字-它的位置,或索引,第一个索引是0,第二个索引是1,依此类推.
python有6个序列的内置类型,但最常见的是列表和元组.
序列都可以进行的操作包括索引,切片,加,乘,检查成员.
此外,python已经内置确定序列的长度以及确定最大和最小的元素的方法.
列表时最长的python数据类型,他可以作为一个方括号内的逗号分隔值出现.
列表的数据项不需要具有相同的类型.
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可,如下所示:
list1=[1,2,3,4]
与字符串的索引一样,列表索引从0开始,列表可以进行截取,组合灯操作.
使用下标索引来访问列表中的值,同样你也可以使用方括号的形式截取字符
list1=['Google','Runoob',1997,2000];
list2=[1,2,3,4,5,6,7];
print("list1[0]:",list1[0])
print("list2[1:5]:",list2[1:5])
list1[0]:Google
list2[1:5]:[2,3,4,5]
你可以对列表的数据项进行修改或更新,你也可以使用append()方法来添加列表项
list=['Google','Runoob',1997,2000]
print("第三个元素为:",list[2])
list[2]=2001
print("更新后的第三个元素为:",list[2])
第三个元素为:1997
更新后的第三个元素为:2001
可以使用del语句来删除列表的元素
list=['Google','Runoob',1997,2000]
print("原始列表:",list)
del list[2]
print("删除第三个元素:",list)
原始列表:['Google','Runoob',1997,2000]
删除第三个元素:['Google','Runoob',2000]
列表对+和*的操作符与字符串相似.
len([1,2])3长度
[1,2]+[3,4][1,2,3,4]组合
['hi']*4['hi','hi','hi','hi']重复
2 in[1,2]True元素是否存在列表中
for x in[1,2,3]:print(x,end="")1 2 3迭代#for循环是迭代循环,后会细讲
Python的列表截取与字符串操作类型,如下所示:
L=['Google','Runoob','Taobao']
操作:
Python表达式 结果 描述
L[2] 'Taobao' 读取第三个元素
L[-2] 'Runoob' 从右侧开始读取倒数第二个元素:count from the right
L[1:] ['Runoob','Taobao'] 输出从第二个元素开始后的所有元素
>>>L=['Google','Runoob','Taobao']
>>>L[2]
'Taobao'
>>>L[-2]
'Runoob'
>>>L[1:]
['Runoob','Taobao']
>>>
列表还支持拼接操作:
>>>squares=[1,4,9,16,25]
>>>squares+=[36,49,64,81,100]
>>>squares
[1,4,9,16,25,36,49,64,81,100]
>>>
使用嵌套列表即在列表里创建其他列表:
>>>a=['a','b','c']
>>>n=[1,2,3]
>>>x=[a,n]
>>>x
[['a','b','c'],[1,2,3]]
>>>x[0]
['a','b','c']
>>>x[0][1]
'b'
列表函数len(list):列表元素个数
max(list):返回列表元素最大值
min(list):返回列表元素最小值
list(seq):将元组转换为列表
列表方法append(obj):在列表末尾添加新的对象
count(obj):统计某个元素在列表中出现的次数
extend(seq):在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
index(obj):从列表汇总找出某个值第一个匹配项的索引位置
insert(index,obj):将对象插入列表
pop([index=-1]):移除列表中的一个元素(默认最后一个元素),并且返回该元素的值,index是可选项
remove(obj):移除列表中某个值的第一个匹配项
reverse():反向列表中元素
sort(cmp=None,key=None,reverse=False):对原列表进行排序,可以使用匿名函数修改排序的规则,后会细讲
clear():清空列表
copy():复制列表
python创建二维列表,将需要的参数写入cols和rows即可
list_2d=[[0 for col in range(cols)]for row in range(rows)]
实例:
>>>list_2d=[[0 for i in range(5)]for i in range(5)]
>>>list_2d[0].append(3)
>>>list_2d[0].append(5)
>>>list_2d[2].append(7)
>>>list_2d
[[0,0,0,0,0,3,5],[0,0,0,0,0],[0,0,0,0,0,7],[0,0,0,0,0],[0,0,0,0,0]]
列表的复制有三种方法,首先设a=[1,2,3,4],第一种a=b,第二种c=[];c=a,第三种d=a[:],前两种都是单纯的把b,c引向a的内存地址,而第四种则是获取a的所有元素.
>>>a=[1,2,3]
>>>b=a
>>>c=[]
>>>c=a
>>>d=a[:]
>>>a,b,c,d
([1,2,3],[1,2,3],[1,2,3],[1,2,3])
>>>b[0]='b'
>>>a,b,c,d
(['b',2,3],['b',2,3],['b',2,3],[1,2,3])
>>>id(a),id(b),id(c),id(d)
(140180778120200,140180778120200,140180778120200,140180778122696)
>>>c[0]='c'
>>>a,b,c,d
(['c',2,3],['c',2,3],['c',2,3],[1,2,3])
>>>id(a),id(b),id(c),id(d)
(140180778120200,140180778120200,140180778120200,140180778122696)
>>>d[0]='d'
>>>a,b,c,d
(['c',2,3],['c',2,3],['c',2,3],['d',2,3])
>>>id(a),id(b),id(c),id(d)
(140180778120200,140180778120200,140180778120200,140180778122696)
可以看到a b c三个是同一id值,当改变当中任一列表元素的值后,三者会同步改变。
但d的元素值不会变,改变d的元素值其它三个变量内的元素值也不会变。
从a b c d的id值来看,a b c地址全一样,唯有d分配了新地址。
所以一般情况下想复制得到一个新列表并改变新列表内元素而不影响原列表,可以采用d的赋值方式。
这只是针对这种比较单一的普通列表。
使用copy模块可以复制一个内存地址不同的列表.
import copy
a=[1,2,3,4]
b=copy.copy(a)
id(a),id(b)#a和b的内存地址不同
使用列表自带方法copy()复制一个不同内存地址的列表:
a=[1,2,3,4]
b=a.copy()
id(a),id(b)#a和b的内存地址不同
有时在取list中元素时可能会遇到以下情形:
>>>a=[]
>>>a[0]
Traceback(most recent call last):
File"<stdin>",line 1,in<module>
IndexError:list index out of range
这种情况发生是因为只定义了一个空列表,没有进行任何的赋值,所以列表里什么也没有,而后面的报错也明确表示了索引超出范围,即写上的0
其实是第一位值的位置,而此时是空列表没有赋值,故而报错。
而如果我们使用以下语句则不会报错:
>>>a[0:]
[]
这个不是什么小技巧,这是不一样的语句意义,这句话其实是把这个列表a里的所有值都输出,其效果和下面表达的最终结果是一致的。
>>>a[:]
[]
而这个语句并不能避免上面报错中超出索引范围的错误,这个根本就是两种不同的意义的语句。a[0:]和a[:]在脚本输出时相当于print(a)
的意思。这不是解决错误的方式,不能将它当成trick来用。
我不知道以后会不会讲,看到了就拷贝给你们看:
1、列表推导式书写形式:
[表达式for变量in列表]
或者
[表达式for变量in列表if条件]
2、举例说明:
#!/usr/bin/python
#-*-coding:utf-8-*-
li=[1,2,3,4,5,6,7,8,9]
print([x**2 for x in li])
print([x**2 for x in li if x>5])
print(dict([(x,x*10)for x in li]))
print([(x,y)for x in range(10)if x%2 if x>3 for y in range(10)if y>7 if y!=8])
vec=[2,4,6]
vec2=[4,3,-9]
sq=[vec[i]+vec2[i]for i in range(len(vec))]
print(sq)
print([x*y for x in[1,2,3]for y in[1,2,3]])
testList=[1,2,3,4]
def mul2(x):
return x*2
print([mul2(i)for i in testList])
结果:
[1,4,9,16,25,36,49,64,81]
[36,49,64,81]
{1:10,2:20,3:30,4:40,5:50,6:60,7:70,8:80,9:90}
[(5,9),(7,9),(9,9)]
[6,7,-3]
[1,2,3,2,4,6,3,6,9]
[2,4,6,8]
3、总结:
我觉得就是通过for语句处理表达式里面的变量,如果还要加条件,就加if条件就可以了。
python的元组与列表类似,不同之处在于元组的元素不能修改.
元组使用小括号,列表使用方括号.
元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可.
>>>tup1=('Google','Runoob',1997,2000);
>>>tup2=(1,2,3,4,5);
>>>tup3="a","b","c","d";#不需要括号也可以
>>>type(tup3)
<class'tuple'>
注意:元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当做运算符使用
>>>tup1=(50)
>>>type(tup1)#不加逗号,类型为整型
<class'int'>
>>>tup1=(50,)
>>>type(tup1)#加上逗号,类型为元组
<class'tuple'>
元组可以使用下标索引来访问元组中的值
tup1=('Google','Runoob',1997,2000)
tup2=(1,2,3,4,5,6,7)
print("tup1[0]:",tup1[0])
print("tup2[1:5]:",tup2[1:5])
tup1[0]:Google
tup2[1:5]:(2,3,4,5)
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合
tup1=(12,34.56);
tup2=('abc','xyz')
#以下修改元组元素操作是非法的。
#tup1[0]=100
#创建一个新的元组
tup3=tup1+tup2;
print(tup3)
(12,34.56,'abc','xyz')
元组中的元素是不允许删除的,但我们可以使用del语句来删除整个元组
tup=('Google','Runoob',1997,2000)
print(tup)
del tup;
print("删除后的元组tup:")
print(tup)
删除后的元组tup:
Traceback(most recent call last):
File"test.py",line 8,in<module>
print(tup)
NameError:name'tup'is not defined
同列表因此复制粘贴:
与字符串一样,元组之间可以使用+号和*号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。
Python表达式 结果 描述
len((1,2,3)) 3 计算元素个数
(1,2,3)+(4,5,6) (1,2,3,4,5,6) 连接
('Hi!',)*4 ('Hi!','Hi!','Hi!','Hi!') 复制
3 in(1,2,3) True 元素是否存在
for x in(1,2,3):print(x,) 1 2 3 迭代
同列表,因此复制粘贴:
因为元组也是一个序列,所以我们可以访问元组中的指定位置的元素,也可以截取索引中的一段元素,如下所示:
元组:
L=('Google','Taobao','Runoob')
Python表达式 结果 描述
L[2] 'Runoob' 读取第三个元素
L[-2] 'Taobao' 反向读取;读取倒数第二个元素
L[1:] ('Taobao','Runoob') 截取元素,从第二个开始后的所有元素。
运行实例如下:
>>>L=('Google','Taobao','Runoob')
>>>L[2]
'Runoob'
>>>L[-2]
'Taobao'
>>>L[1:]
('Taobao','Runoob')
len(tuple):计算元组元素个数
max(tuple):返回元祖中元素最大值
min(tuple):返回元组中元素最小值
tuple(seq):将列表转换为元组
>>>t=('a','b',['A','B'])
>>>t[2][0]='X'
>>>t[2][1]='Y'
>>>t
('a','b',['X','Y'])
这个tuple定义的时候有3个元素,分别是'a','b'和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?
别急,我们先看看定义的时候tuple包含的3个元素:当我们把list的元素'A'和'B'修改为'X'和'Y'后,tuple变为:表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的"不变"是说,tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!理解了"指向不变"后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
有兴趣的自行研究!!!
Python元组的升级版本--namedtuple(具名元组)
因为元组的局限性:不能为元组内部的数据进行命名,所以往往我们并不知道一个元组所要表达的意义,所以在这里引入了collections.namedtuple这个工厂函数,来构造一个带字段名的元组。具名元组的实例和普通元组消耗的内存一样多,因为字段名都被存在对应的类里面。这个类跟普通的对象实例比起来也要小一些,因为Python不会用__dict__来存放这些实例的属性。
namedtuple对象的定义如以下格式:
collections.namedtuple(typename,field_names,verbose=False,rename=False)
返回一个具名元组子类typename,其中参数的意义如下:
typename:元组名称
field_names:元组中元素的名称
rename:如果元素名称中含有python的关键字,则必须设置为rename=True
verbose:默认就好
下面来看看声明一个具名元组及其实例化的方法:
import collections
#两种方法来给namedtuple定义方法名
#User=collections.namedtuple('User',['name','age','id'])
User=collections.namedtuple('User','name age id')
user=User('tester','22','464643123')
print(user)
collections.namedtuple('User','name age id')创建一个具名元组,需要两个参数,一个是类名,另一个是类的各个字段名。后者可以是有多个字符串组成的可迭代对象,或者是有空格分隔开的字段名组成的字符串(比如本示例)。具名元组可以通过字段名或者位置来获取一个字段的信息。
输出结果:
User(name='tester',age='22',id='464643123')
具名元组的特有属性:
类属性_fields:包含这个类所有字段名的元组类方法_make(iterable):接受一个可迭代对象来生产这个类的实例实例方法_asdict():把具名元组以collections.OrdereDict的形式返回,可以利用它来把元组里的信息友好的展示出来
from collections import namedtuple
#定义一个namedtuple类型User,并包含name,sex和age属性。
User=namedtuple('User',['name','sex','age'])
#创建一个User对象
user=User(name='Runoob',sex='male',age=12)
#获取所有字段名
print(user._fields)
#也可以通过一个list来创建一个User对象,这里注意需要使用"_make"方法
user=User._make(['Runoob','male',12])
print(user)
#User(name='user1',sex='male',age=12)
#获取用户的属性
print(user.name)
print(user.sex)
print(user.age)
#修改对象属性,注意要使用"_replace"方法
user=user._replace(age=22)
print(user)
#User(name='user1',sex='male',age=21)
#将User对象转换成字典,注意要使用"_asdict"
print(user._asdict())
#OrderedDict([('name','Runoob'),('sex','male'),('age',22)])
以上实例输出结果为:
('name','sex','age')
User(name='Runoob',sex='male',age=12)
Runoob
male
12
User(name='Runoob',sex='male',age=22)
OrderedDict([('name','Runoob'),('sex','male'),('age',22)])
可以先使用list()将元组转换成列表,然后对列表进行修改,之后再将列表用tuple()转化成元组.其次,也可也使用元组的'+'拼接对元组的值进行增加.