大师网-带你快速走向大师之路 解决你在学习过程中的疑惑,带你快速进入大师之门。节省时间,提升效率

Python 列表

"""列表是Python内置的可变序列,是包含若干元素的有序连续内存空间.
当列表增加或者删除元素的时候,列表的对象自动进行内存的扩展和伸缩。
从而保证元素之间没有空隙。但是这涉及到列表元素的移动,效率较低。
尽量的从列表的尾部进行删除和或增加操作以提高处理速度。

Python 中是基于值的内存管理方式
"""
>>> b = 200
>>> id(b)
4297642720
>>> c = "str"
>>> id(c)
4299118496
>>> c = [a, b, c]
>>> c
[100, 200, 'str']
>>> d = [a, b, c]
>>> d
[100, 200, [100, 200, 'str']]
>>> id(a)
4297639520
>>> id(b)
4297642720
>>> id(c)
4330133512
>>> 
# 即使是放到了列表中,该对象所在的内存地址依然不变。

#list.apped(x)  x对象添加到列表的最后。
>>> c.append("abc")
>>> c
[100, 200, 'str', 'abc']
>>> d
[100, 200, [100, 200, 'str', 'abc']]
>>> 
#list.extend(L)  L列表中的所有元素拼接到list的尾部。
>>> d.extend([1, "2"])
>>> d
[100, 200, [100, 200, 'str', 'abc'], 1, '2']
>>> 
#list.insert(index, x) 把 x对象插入到列表的index 处
>>> d.insert(1, "insert")
>>> d
[100, 'insert', 200, [100, 200, 'str', 'abc'], 1, '2']
#list.remove(x) 删除列表中首次出现的 x对象
>>> d.remove(200)
>>> d
[100, 'insert', [100, 200, 'str', 'abc'], 1, '2']
>>> d.remove(300)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
#list.pop(index)  删除并返回对应index的对象,默认为最后一个
>>> d.pop(1)
'insert'
>>> d
[100, [100, 200, 'str', 'abc'], 1, '2']
#list.clear() 删除列表中的所有元素,但是保留列表对象 !!!!
>>> a = 1
>>> b = 2
>>> c = [a, b]
>>> c.clear()
>>> c
[]
>>> a
1
>>> b
2
#list.index(x)  返回值为  x 的下表,列表中没有这个元素,返回异常
>>> d
[1, 2, 3, [100, [100, 200, 'str', 'abc'], 1, '2']]
>>> d.index(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 0 is not in list
>>> d.index(1)
0
#list>>> d
[1, 2, 3, [100, [100, 200, 'str', 'abc'], 1, '2']]
>>> d.index(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 0 is not in list
>>> d.index(1)
0
#list.count(x) 返回x在列表中出现的次数
>>> d.count(1)
1
>>> d.count(4)
0

#list.reverse() 对列表进行翻转,翻转之后列表的内存地址不变
>>> d.reverse()
>>> d
[[100, [100, 200, 'str', 'abc'], 1, '2'], 3, 2, 1]
#list.sort() 对列表进行排序,内存地址不变,元素之间若是无法直接排序,抛出异常
>>> d
[1, 2, 3, [100, [100, 200, 'str', 'abc'], 1, '2']]
>>> d.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'list' and 'int'
>>> e = [1, 3, 5, 2, 4]
>>> e.sort()
>>> e
[1, 2, 3, 4, 5]
#list.copy() 对列表进行浅拷贝
>>> e
[1, 2, 3, 4, 5]
>>> id(e)
4333797512
>>> f = e.copy()
>>> f
[1, 2, 3, 4, 5]
>>> id(f)
4333797576


# 列表的创建与删除
# 直接创建
>>> list1 = [1, 2, 3, "str", ["list"]]
# 使用list()函数,将可迭代对象转换为列表。
>>> list1 = [1, 2, 3, "str", ["list"]] #字符串转列表
>>> listStr = list("abc")
>>> listStr 
['a', 'b', 'c']
>>> listTuple = list((1, 2, 3, 5))      #元组转列表
>>> listTuple
[1, 2, 3, 5]
#配合range函数
>>> listRange = list(range(10, 19, 3)) #依次是,初始值,终点值(不包括终点值),步数
>>> listRange
[10, 13, 16]

# 删除
>>> del list1
>>> list1   #删除后再次访问该对象,抛出异常,如果列表指向的值不在有对象指向,Pyhton将删除该值。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'list1' is not defined
>>> list0 = [listStr,listTuple]
>>> list0
[['a', 'b', 'c'], [1, 2, 3, 5]]
>>> del list0
>>> listStr
['a', 'b', 'c']

#列表元素的增加与删除
#增加
"""
使用+ 运算符来实现列表的拼接。虽然这种方式看起来比较通俗简单,但是这并不是真正的对
列表进行拼接,而是通过两个列表来创建一个新的列表,并且将两个列表之中的元素依次复制
到新列表的内存空间中。由于涉及到大量元素的赋值,该操作的速度较慢,在涉及大量元素添
加的时候不建议使用。
"""
>>> list1 = [123]
>>> list2 = [234]
>>> list4 = list1 + list2
>>> list4
[123, 234]

#上面讲过的append方法,对列表添加一个对象。
>>> list1.append("str")
>>> list1
[123, 'str']
#原地直接拼接,并没有用新的列表来接,直接对list1 进行操作。
#通过list_demo_01.py 打印的结果可以看到 两者的运行速度差了 70倍左右

"""
前面提到过Python 是采用基于值的自动内存管理方式,当为变量修改值的时候并不是直接
修改变量指向内存的值而是,是变量指向新的值。

对于列表,集合,字典等可变序列类型而言。以序列为例,列表中包含的是元素值的内存地址,
而不是直接包含元素的值。如果是直接修改列表变量的值,则与修改普通对象一致。当通过修
改下标来修改序列中的值时,或者使用可变序列自身提供的增加删除方法时,序列在内存中的
地址是不变的。
"""
>>> list1
[123, 'str']
>>> id(list1)
4331182088
>>> list1[0] = 111
>>> list1
[111, 'str']
>>> id(list1)
4331182088

#extend 方法 也属于原地操作,不改变地址。
"""
insert()方法 插入操作。列表的insert()方法可以在列表的任意位置插入对象。但是
,由于Python 采用基于值的自动内存管理方式,insert()方法会涉及到插入位置之后所
所有元素的移动,这会影响处理速度。remove 也有这个特点 通过list_demo_02.py 
可以看出性能的差别有多大
"""

#使用乘法来扩展列表对象。 生成一个新的列表。
>>> id(list1)
4331193352
>>> list1 = list1 * 2
>>> list1
['zz', 111, 'str', 'zz', 111, 'str']
>>> id(list1)
4331193416

#使用del 删除列表对应index 的对象
>>> del list1[1]
>>> list1
['zz', 'str', 'zz', 111, 'str']

#pop() 和 remove 删除的使用类似。
"""
remove() 用来删除多个重复的对象时容易出现问题。当正向遍历删除对象时,因为在删除
对象时,列表会自动收缩。所以每次删除一个对象时,后面的对象在列表中的index会减1.
造成循环一次删除的时候会少删除一些的问题。
正确的方式 是通过倒序遍历的方式来实现。看list_demo_03.py里面的代码
"""

##列表元素访问与计数
#使用下标访问元素,越界时报出异常。

#使用内置函数 index(value,[start,[stop]]) 获取在下标 start 到 stop 之间出现的index
>>> list1
['zz', 'str', 'zz', 111, 'str']
>>> list1.index('zz')
0
>>> list1.index('zz',1,5)
2

#使用count(x) 获取在x在列表中出现的次数

#成员资格判断
>>> 'zz' in list1
True
>>> 'zz' not in list1
False
>>> 

>>> list1
['zz', 'str', 'zz', 111, 'str']
>>> list2
[234]
>>> ('zz',234) in (list1, list2)
False
>>> ('zz',234) in zip(list1, list2) #注意zip
True

# 切片操作
"""
切片操作是python 序列中的一个重要操作,适用于列表,元组,字符串,range对象等类型
切片操作通过两个冒号和三个数字来完成图,依次表示起始位置,终点位置(不包含),步数
切片操作不会因为列表越界而抛出异常。
"""
>>> list1
['zz', 'str', 'zz', 111, 'str']
>>> list1[::]
['zz', 'str', 'zz', 111, 'str']
>>> list1[::2]
['zz', 'zz', 'str']
>>> list1[:2:2]
['zz']
>>> list1[:2:1]
['zz', 'str']
>>> list1[::-1]
['str', 111, 'zz', 'str', 'zz']
>>> list1[0:5:-1]
[]
>>> list1[5:0:-1]
['str', 111, 'zz', 'str']
>>> 
#切片操作可以用来快速的实现很多的功能,如
#原地修改列表内容
#元素列表的增删改查
#元素替换。
>>> list1
['zz', 'str', 'zz', 111, 'str']
>>> list1[:3] = [1, 2, 3]
>>> list1
[1, 2, 3, 111, 'str']
>>> list1[:3] = [1, 2]
>>> list1
[1, 2, 111, 'str']
>>> del list1[:2]
>>> list1

#以上操作都不影响列表对象的内存地址
"""
需要注意的是 列表的切片操作返回的是对象的浅复制,与对象的赋值并不一样。
这个操作是返回一个和之前列表对象对应相等的新列表,可能值相等,但是内存地址
不一样的。
"""

python 列表拼接性能对比

import time
result = []
start = time.time()
for i in range(1,10000):
    result = result + [i]
    if i == 1000:
        print(len(result),',',time.time() - start)
        pass
    pass

result = []
start = time.time()
for i in range(1,10000):
    result.append(i)
    if i == 1000:
        print(len(result),',',time.time() - start)
        pass
    pass
"""
1000 , 0.0014491081237792969
1000 , 0.00021886825561523438
"""

python 列表中间对象操作和尾部操作性能差异

import time
def Insert():
    a = []
    for x in range(1000):
        a.insert(0,x)
        pass
    pass

def Append():
    a = []
    for x in range(1000):
        a.append(x)
        pass
    pass

start = time.time()
for x in range(1,10):
    Insert()
    pass
print ('Insert :',time.time() - start)

start = time.time()
for x in range(1,10):
    Append()
    pass
print ('Insert :',time.time() - start)
"""
Insert : 0.003637075424194336
Insert : 0.000982046127319336
"""

python 列表操作 内置函数remove 使用容易产生的问题

list1 = [1, 1, 1, 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1]
for x in list1:
    if x == 1:
        list1.remove(1)
        pass
    pass
print (list1)
#[1, 1, 1, 1, 1]
list1 = [1, 1, 1, 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1]
for x in list1[::-1]:
    if x == 1:
        list1.remove(1)
        pass
    pass
print (list1)
#[]

zip() 的使用

lista = [1, 2, 3, 4, 5, 6, 7]
listb = ['a', 'b', 'c', 'd']
for a,b in zip(lista,listb):
    print(a,b)
    pass

for a,b in zip(listb,lista):
    print(a,b)
    pass
"""
1 a
2 b
3 c
4 d
a 1
b 2
c 3
d 4
"""

列表的排序

#列表排序demo
import random
l1 = [1, 2, 4, 5, 6, 7, 8, 11, 123, 3333]
random.shuffle(l1)
print (l1)
l1.sort()
print (l1)
l1.sort(reverse = True)
print (l1)

'''
[4, 8, 1, 11, 2, 5, 6, 7, 3333, 123]
[1, 2, 4, 5, 6, 7, 8, 11, 123, 3333]
[3333, 123, 11, 8, 7, 6, 5, 4, 2, 1]
'''