Python(7)——Python入门之列表&元组&深拷贝浅拷贝区别


前言

1、列表(python中用的最多的一个数据类型)

1.1 列表的创建

li = []
print(li, type(li))
li1 = [1]
print(li1, type(li1))

1.2 列表的基本特性

# 1. 连接操作符和重复操作符
print([1, 2] + [2, 3]) # [1, 2, 2, 3]
print([1, 2] * 3) # [1, 2, 1, 2, 1, 2]

# 2. 成员操作符(in, not in)
print(1 in [1, 2, 3]) # True
print(0 in [1,2,3])  #False
"""
布尔类型:
    True: 1
    False:0
"""
print(1 in ["a", False, [1, 2]])  # False
print(1 in ["a", True, [1, 2]])  # True ,因为True默认为1.

# 3. 索引
li = [1, 2, 3, [1, 'b', 3]]
print(li[0])  # 1
print(li[-1]) # [1, 'b', 3]
print(li[-1][0])  # 1
print(li[3][-1])  # 3

# 4. 切片
li = ['172', '25', '254', '100']
print(li[:2])
print(li[1:])
print(li[::-1])
# 需求: 已知['172', '25', '254', '100'], 输出: "100-254-25"
li = ['172', '25', '254', '100']
print("-".join(li[1:][::-1]))

# 5. for循环
names = ["粉丝", '粉条', '粉带']
for name in names:
    print(f"西部开源猫大佬的姓名是:{name}")

"""
['172', '25', '254', '100']
>>> # 需求: 将四个数字用'-'拼接起来
>>> "-".join(items)
'172-25-254-100'
>>>
"""

# 需求: 已知['172', '25', '254', '100'], 输出: "100-254-25"
li = ['172', '25', '254', '100']
print("-".join(li[1:4][::-1]))  #  方法1
print("-".join(li[3:0:-1]))     #  方法2
print("-".join(li[1:][::-1]))   #  方法3

在这里插入图片描述

1.3 对列表操作常用方法(增删改查)

1.3.1 增加

# 1-1). 追加
li = [1, 2, 3]
li.append(4)
print(li)
# 1-2). 在列表开头添加
li = [1, 2, 3]
li.insert(0, 'cat')
print(li)
# 1-2). 在索引2前面添加元素cat
li = [1, 2, 3]
li.insert(2, 'cat')
print(li)
# 1-3). 一次追加多个元素
li = [1, 2, 3]  # 添加4, 5, 6
li.extend([4, 5, 6])
print(li)

1.3.2 修改: 通过索引和切片重新赋值的方式。

li = [1, 2, 3]
li[0] = 'cat'
li[-1] = 'westos'
print(li)
li = [1, 2, 3]
li[:2] = ['cat', 'westos']
print(li)

1.3.3 查看: 通过索引和切片查看元素。 查看索引值和出现次数。

li = [1, 2, 3, 1, 1, 3]
print(li.count(1))   # 3
print(li.index(3))   # 2

1.3.4 删除

# 4-1). 根据索引删除
li = [1, 2, 3]
# 将pop方法的结果存储到delete_num变量中。
delete_num = li.pop(-1)
print(li)
print("删除的元素是:", delete_num)

# 4-2). 根据value值删除
li = [1, 2, 3]
li.remove(1)
print(li)

# 4-3). 全部清空
li = [1, 2, 3]
li.clear()
print(li)

2、元组

2.1 元组的创建

# 元组tuple(戴了紧箍咒的列表, 不能修改元素)
# 元组的创建
t1 = ()    # 空元组
print(t1, type(t1))
t2 = (1,)   # 重要(易错点):元组只有一个元素时一定要加逗号
print(t2, type(t2))
t3 = (1, 1.2, True, [1, 2, 3])
print(t3, type(t3))

2.2 元组的基本特性

# 特性
print((1, 2, 3) + (3,))
print((1, 2, 3) * 2)
print(1 in (1, 2, 3))
t = (1, 2, 3)
print(t[0])
print(t[-1])
print(t[:2])
print(t[1:])
print(t[::-1])

2.3 元组的使用方法–查看(不可以增删改)

# 查看: 通过索引和切片查看元素。 查看索引值和出现次数。
t = (1, 2, 3, 1, 1, 3)
print(t.count(1))   # 3
print(t.index(3))   # 2

3、命名元组的操作(扩展)

tuple = ("westos", 18, "西安")
print(tuple[0], tuple[1], tuple[2])

# 从collections模块中导入namedtuple工具。
from collections import  namedtuple
# 1. 创建命名元组对象User
User = namedtuple('User', ('name', 'age', 'city'))
# 2. 给命名元组传值
user1 = User("westos", 18, "西安")
# 3. 打印命名元组
print(user1)
# 4. 获取命名元组指定的信息
print(user1.name)
print(user1.age)
print(user1.city)

4、is 和 == 的区别

"""
python语言:
    ==: 类型和值是否相等
    is: 类型和值是否相等, 内存地址是否相等

"""
print(1 == '1')   # False
li = [1, 2, 3]
li1 = li.copy()
print(li == li1)  # True

# 查看内存地址
print(id(li), id(li1))
print(li is li1)  # False

5、深拷贝与浅拷贝区别

5.1 概述

首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。

什么是可变对象,什么是不可变对象

  • 可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值;

  • 不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了,但是可变对象就不会做这样的动作,而是直接在对象所指的地址上把值给改变了,而这个对象依然指向这个地址。

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝

  • 在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

5.2 举例说明

#encoding=utf-8

import copy
a=[1,2,3,4,5,['a','b']]
#原始对象
b=a                  #赋值,传对象的引用
c=copy.copy(a)       #对象拷贝,浅拷贝
d=copy.deepcopy(a)   #对象拷贝,深拷贝
print "a=",a,"    id(a)=",id(a),"id(a[5])=",id(a[5])
print "b=",b,"    id(b)=",id(b),"id(b[5])=",id(b[5])
print "c=",c,"    id(c)=",id(c),"id(c[5])=",id(c[5])
print "d=",d,"    id(d)=",id(d),"id(d[5])=",id(d[5])
print "*"*70

a.append(6)          #修改对象a
a[5].append('c')     #修改对象a中的['a','b']数组对象
print "a=",a,"    id(a)=",id(a),"id(a[5])=",id(a[5])
print "b=",b,"    id(b)=",id(b),"id(b[5])=",id(b[5])
print "c=",c,"       id(c)=",id(c),"id(c[5])=",id(c[5])
print "d=",d,"            id(d)=",id(d),"id(d[5])=",id(d[5])

结果:

在这里插入图片描述

5.3 小结

  • 从程序的结果来看,列表a和b是赋值操作,两个对象完全指向同一个地址,a和b就是同一块地址的两个引用,其实就是一个东西,所以一个对象在修改浅层元素(不可变)或深层元素(可变)时,另一个对象也同时在变;

  • c是a进行浅拷贝生成的对象,可以看到a(或b)和c两个对象整体的id是不同的,但是里面的第5个元素-列表的地址却是相同的(指向同一个地址),所以b在浅层次元素层面(不可变)增加一个元素时,c并没跟着增加,但是b的第5个元素-列表在增加一个元素时,c的第5个元素也跟着增加了,这就是因为b和c的第5个元素-列表是指向同一个地址的,这个地址上的值变了,在两个地方会同时改变;

  • 再看d,d的浅层次元素(不可变)和 深层次元素(可变)的地址和a,b,c都不一样,所以,a,b,c无论怎么修改,d都不会跟着改变,这就是深拷贝的结果。

也可以这样理解:

  • 深拷贝就是完全跟以前就没有任何关系了,原来的对象怎么改都不会影响当前对象

  • 浅拷贝,原对象的list元素改变的话会改变当前对象,如果当前对象中list元素改变了,也同样会影响原对象。

  • 通常复制的时候要用深拷贝,因为浅拷贝后,两个对象中不可变对象指向不同地址,相互不会改变,但是两个对象中的可变元素是指向相同的地址,一个变了,另一个会同时改变,会有影响(list是可变对象)。

6、练习题

"""
编写一个云主机管理系统:
    - 添加云主机(IP, hostname,IDC)
    - 搜索云主机(顺序查找)
    - 删除云主机
    - 查看所有的云主机信息
"""
from collections import  namedtuple
menu = """
                云主机管理系统
        1). 添加云主机
        2). 搜索云主机(IP搜索)
        3). 删除云主机
        4). 云主机列表
        5). 退出系统
        
请输入你的选择: """

# 思考1. 所有的云主机信息如何存储?选择哪种数据类型存储呢?  选择列表
# 思考2: 每个云主机信息该如何存储?IP, hostname,IDC   选择命名元组
hosts = []
Host = namedtuple('Host', ('ip', 'hostname', 'idc'))
while True:
    choice = input(menu)
    if choice == '1':
        print('添加云主机'.center(50, '*'))
        ip = input("ip:")
        hostname = input("hostname:")
        idc = input('idc(eg:ali,huawei..):')
        host1 = Host(ip, hostname, idc)
        hosts.append(host1)
        print(f"添加{idc}的云主机成功.IP地址为{ip}")
    elif choice == '2':
        print('搜索云主机'.center(50, '*'))
        # 今天的作业: for循环(for...else),判断, break
    elif choice == '3':
        print('删除云主机'.center(50, '*'))
        # 今天的作业:(选做)
    elif choice == '4':
        print('云主机列表'.center(50, '*'))
        print("IP\t\t\thostname\tidc")
        count = 0
        for host in hosts:
            count += 1
            print(f'{host.ip}\t{host.hostname}\t{host.idc}')
        print('云主机总个数为', count)
    elif choice == '5':
        print("系统正在退出,欢迎下次使用......")
        exit()
    else:
        print("请输入正确的选项")


测试:

猜你喜欢

转载自blog.csdn.net/weixin_41191813/article/details/113701102
今日推荐