Python10_列表及深浅拷贝混讲

列表list

列表和C里面的数组很像,但是list可以存储不同的数据类型

需求,存储5个人的年龄,求他们的平均年龄

目前:定义5个变量,然后求和

如果数据过多呢?怎么解决?用列表!

列表的本质:有序的集合

创建列表

格式:列表名 = [列表选项1,列表选项2……列表选项n]

list = []   #空列表
print(list) #输出"[]"
#注意:列表中的元素的数据可以是不同类型
list2 = [1, 2, "Tom", True]
print(list2)

列表元素的访问

取值

格式:列表名[下标]

list3 = [1,2,3,4,5]
print(list3)

替换

list[2] = 100
print(list4)

注意,列表下标不能越界

ps:层级的嵌套最好不要超过3层

基础

列表组合

list5 = [1, 2, 3]
list6 = [4, 5, 6]
list7 = list5 + list6
print(list7)

列表的重复

list8 = [1, 2, 3]
print(list8 * 3)    #将列表的元素复制5份

判断元素是否在列表中

list9 = [1,2,3,4]
print(3 in list9)  #输出True
print(9 in list9)   #输出False

列表截取

list10 = [1,2,3,4,5,6,7,8,9]
print(list10[2:4])
print(list10[:7])
print(list10[3:])

多维列表

list11 = [[1,2,3],[4,5,6],[7.8,9]])
print(list11[1][2])

列表的截取、重复等方法基本和字符串一样

列表方法之列表为调用者

append

在列表的末尾添加新的元素,即将参数作为一个元素,不管是基本数据类型还是列表

list12 = [1,2,4,5]
list12.append(6)
list12.append([7,8.9])
print(list12)   #输出[1,2,4,5,7,8,9]

extend

在末尾一次性追加另一个列表中的多个值,即,参数必须为列表

list13 = [1,2,3,4,5]
list13.extend([6,7,8])
print(list13)   #输出[1,2,3,4,5,6,7,8]

insert

在指定位置(下标前)插入元素,参数可以是列表或基本数据类型,如果是列表,当作一个元素来看待

list14 = [1,2,3,4,5]
list14.insert(1,100)
print(lsit14)   #输出[1,100,2,3,4,5]
list14.insert(3,[1,3,5])

pop

list.pop(x = -1)

移除列表中指定下标处的元素,默认移除最后一个元素,并返回删除的数据

list15 = [1,2,3,4,5]
list15.pop()
print(list15)
list15.pop(1)

del

根据下标进行删除

#ps:del的功能就是用于删除变量
name_list=["鲁班","小明"]
del name_list[0]
print(name_list)

remove

根据元素进行删除

移除列表中的某个元素第一个匹配的结果

list16 = [1,2,3,4,5]
list16.remove(3)
print(list16)

clear

清空列表中所有的数据

list17 = [1,2,3,4,5]
print(list17)
list17.clear()
print(list17)

in/not in

name_list=["鲁班","小明"]
find_name = "小明"
if find_name in name_list:
    print("小明在列表里面")
if "老王" not in name_list:
    print("老王没有在列表里面")

index

  • index(ele[,start[,end]])

*从列表中找出某个值第一个匹配的索引值,实际索引,不是相对于start

list18 = [1,2,3,4,5,1,2,3,4,5]
print(list18.index(3))
print(list18.index(3,3,8))

count

list23= [1,2,3,4,2,3,4,3,3,3,5]
print(list23.count(3))

#删除列表中所有的3
num = 0
all = list23.count(3)
while num < all:
    list23.remove(3)
    num += 1
print(list23)

reverse

倒序

list25 = [5.4.3.2.1]
list25.reverse()
print(list25)

sort

排序

list26 = [1,2,3,3,12,4,5]
list26.sort()
print(list26)
#升序
#逆序
list26.sort(reverse=True)
print(list6)

拷贝

  • =

等于符号赋值的是引用

list27 = [1,2,3,4,5]
list28 = list27
list28[1] = 200
print(list27)
print(list28)
#会发现list27和list28都被修改了
print(id(list27))
print(id(list28))
#会发现两个id相同

  • copy

深拷贝,又被称为内存拷贝

list29 = [1,2,3,4,5]
list30 = list29.copy()
list30[1] = 100
print(list29)
print(list30)
#会发现list29没有被修改
#python中的赋值(等号),都是复制的引用

import copy

a = ["zhao4","wang5"]
b = copy.copy(a)
print(id(a)," ", id(b)) # 会发现a,b的id不同,但是如果查看a[0]和b[0],会发现他们相同,即copy.copy拷贝的是最上面一层

de_list = ["zhang3",s_list]
deb_list = copy.copy(de_list)   # copy.copy由于是浅拷贝,只拷贝最上一层
# 但是如果用copy.copy拷贝的元组,由于元组不可变,那么直接共用就行了,所以就是直接为新的变量添加指向,而不会进行浅拷贝

de_list[1][0] = None
d_list = list(de_list)  #还是相当于浅拷贝
e_list = de_list[:] #浅拷贝
print(de_list," ", deb_list)
#对于copy模块中的copy方法,如果拷贝的是不可变元素,对拷贝内容本身。如果元素是可变元素,会拷贝元素的地址。——浅拷贝

#深拷贝时,会拷贝可变元素本身,而不是地址
#所谓深,即不管怎么引用,都能拷出来,即最后拷贝的总是内存空间的实际存储数据,而不会仅仅是引用
dee_list = copy.deepcopy(deb_list)  # 深拷贝,除了copy.deepcopy()外的拷贝都是浅拷贝
deb_list[1][0] = "biubiu~"
print(deb_list," ", dee_list)

copy.copy与copy.deepcopy

  1. 如果用copy.copy、copy.deepcopy对一个全部都可不可变类型的数据进行拷贝,那么他们id()的结果相同,都是引用指向
  2. 如果拷贝的是一个拥有不可变类型的数据,即使元组位于最顶层,那么deepcopy依然是深拷贝而copy.copy还是指向

列表的嵌套

a = [1,2,3]
b = [4,5,6]
c = [a,b]
#解析:a指向了一块地址,里面存有123,b也指向了一块地址,里面存有456,c里面实际存储的是a和b的引用,即里面是分别指向两块地址。
# d = c
e = c.copy()    #浅拷贝

将元组转成列表

list31 = list((1,2,3,4))    #元组用小括号
print(list31)

列表方法之列表为参数

len

返回列表中元素个数,同字符串

list20 = [1,2,3,4,5]
print(len(list20))  #输出5

max/min

获取列表中的最大值与最小值

list22 = [1,2,3,4,5]
print(max(list22))
print(min(list22))

join()

将列表转为字符串

list = ["my","name","is","Tom"]
print(" ".join(list))

sorted(Iterator)

可以对任意可迭代对象进行排序

  • 与“.sort()“的区别
  1. .sort()是对原来的列表进行修改排序,而sorted()是返回一个新的列表,不对原列表进行修改
  2. .sort()属于列表的成员方法,sorted()可对所有可迭代对象(Iterable)进行操作
  3. 调用形式不一样,myList.sort(key, reverse)。sorted(myList)

列表推导式【重要】

ps:列表推导式的效率比循环的效率高

所谓的列表推导式,就是指轻量级的列表循环创建

#之前的做法
list1 = []
for i in range(10):
    list1.append(i)
    
#用列表推导式
from random import randint 
list2 = [i for i in range(10)]
print(list2)

list2 = []
for _ in range(10):
    list2.append("不给我鲁班我就送")

#用列表推导器
list4 = ["不给我鲁班我就送" for _ in range(10)]
print(list4)

#生成10个元素的列表,其元素值在-10到10
from random import randint
l = [randint(-10,10) for _ in range(10)]
print(l)

#选出大于等于0的数据

#正常,使用for循环筛选
res = []
for x in l: #l为上面的列表
    if x >= 0:
        res.append(x)
print(res)

#循环的过程中使用if,用列表解析筛选
res2 = [x for x in l if x >= 0] #注意,最前面的x为返回值

翻外

之zip

zip(Iterable1, Iterable2)

zip()用于将可迭代对象作为参数,将对象中的对应的元素打包成一个元组,然后返回这些元组对象,节约内存

如果长度不一致,与最短的对象相同

a = [1,2,3]
b=[4,5,6]
print(list(zip(a,b))    #将zip对象转换为list并打印

#同时迭代多个列表
heros = ["后弈","安齐拉"]
skills = ["惩戒之箭","火球术"]
for hero,skill in zip(heros,skills):
    print(hero+"——>"+skill)

之内存两区(深浅拷贝的解析)

  • 堆区、栈区
    栈区系统自动分配,程序结束自动释放内存空间
    堆区程序员手动开辟,手动释放,但是有一种机制可以帮程序员做到这件事情
    实际上list中的数据存在堆区,栈区内的的空间存的是对应堆区的地址,通过该地址可以区出堆内的list空间的数据,list用等号赋值拷贝时,实际上是将堆区的地址给了新的变量,故浅拷贝又被称为地址拷贝,而用copy方法进行深拷贝时,对在堆区重新开辟一个空间,并将数据复制进去

深浅拷贝以及赋值

赋值是添加指向,浅拷贝是拷贝最上层的,深拷贝是将所有数据(不管中间有多少层引用)都进行拷贝

之元组

存储多个数据

nums = (1,2,3)
print(type(nums))   #输出tuple

列表vs.元组

二者非常相似,但是列表增、删查、改都可以,而元组除了定义时不可以改(增加、删除),用法和列表相同

之循环的运用

计算单词数

#判断句子中单词个数
str = input("please input a sentence:\n")
str.strip()
count = index = 0
while index < len(str):
    #当下一个不为空格,说明一个单词还没有完,index += 1
    while str[index] != " ":
        index += 1
        #如果index == len(str) -1, 说明已经到最后一个字符,调出循环,避免下标越界
        if index == len(str) - 1:
            break
    # 如果index == len(str) -1, 说明已经到最后一个字符,调出循环,避免下标越界
    if index == len(str) - 1:
        break
        
    count += 1
    #找到空格后,如果后续有多个空格,连续跳过
    while str[index] == " ":
        index += 1
print(count)

之dir

print(dir(" ")) #可以查看字符串的所有方法

print(dir([]))  #可以查看列表的所有方法

知识点补充

a = [100]
def test(num):
    num += num
    print(num)
test(a)
print(a)
#输出:两个[100, 100]

#如果test方法变了
def test(num):
    num = num + num
    print(num)
#则输出:[100, 100]和[100]

  • 对于num += num,实际上并不是执行num =num + num。因为python有一个特点,所有东西并不是真正把这个值复制了,而是复制的都是引用,所以,对于a为引用类型的情况下,num += num,实际上是先num+num,则在一个内存中放的是[100,100],则对于如上函数,因为是在函数体内,所以是在函数体内让num指向了这片空间,然而函数的本质是传值,函数完之后,外面的a仍然是志向[100]所在的空间。对于C、C++等语言,a=a+a和a+=a是完全一样的

你可能感兴趣的:(Python10_列表及深浅拷贝混讲)