一.序列
(一)成员有序排列的,且可以通过下标偏移量访问到它的一个或者几个成员,这类类型统称为序列。
(二)序列数据类型包括:字符串,列表,和元组类型。
(三)特点: 都支持下面的特性
1.索引与切片操作符
2.成员关系操作符(in , not in)
3.连接操作符(+) & 重复操作符(*)
二.列表:更加强大的数组
数组: 存储同一种数据类型的集和。scores=[12,95.5]
列表: 可以存储任意数据类型的集和
# 创建一个空列表
list = []
# 创建一个包含元素的列表,元素可以是任意类型,包括数值类型,列表,字符串等均可, 也可以嵌套列表。
list = ["fentiao", 4, 'gender']
list = [['粉条', 100], ["粉丝", 90], ["粉带", 98]]
# 一个小问题是它会导致出现 Bug ,并且这个问题是难以追踪的,因为它在运行时不会引发错误
li = [[2, 3, 4], 'a', 'b', 'c', 'd', 'e', [1, 2, 3]]
print(li[10:]) #注:li[10:]将输出 [] ,并且不会导致一个 IndexError
(一)列表的基本特性
# 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
"""
布尔类型:
True: 1
False:0
"""
print(1 in ["a", False, [1, 2]]) # False
# 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}")
(二)列表的常用方法
# 1. 增加
# 1-1). 列表可通过append追加一个元素到列表中(追加)
li = [1, 2, 3]
li.append(4)
print(li)
# 1-2). 指定位置添加元素使用insert方法,在列表开头添加
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). 列表可通过extend方法拉伸, 实现追加多个元素到列表中
li = [1, 2, 3] # 添加4, 5, 6
li.extend([4, 5, 6])
print(li)
# 2. 修改: 通过索引和切片重新赋值的方式。
li = [1, 2, 3]
li[0] = 'cat'
li[-1] = 'westos'
print(li)
li = [1, 2, 3]
li[:2] = ['cat', 'westos']
print(li)
# 3. 查看: 通过索引和切片查看元素。 查看索引值和出现次数。
li = [1, 2, 3, 1, 1, 3]
print(li.count(1)) # 3 出现次数
print(li.index(3)) # 2 索引值;找到第一个目标就返回值
# 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)
# 5. 其他操作
li = [18, 6, 99, 56]
li.reverse() # 反转,类似于li[::-1]
print(li)
# sort排序默认由小到大。 如果想由大到小排序,设置reverse=True
li.sort(reverse=True)
print(li)
li1 = li.copy() #查看ID
print(id(li), id(li1))
print(li, li1)
三.元组
# 元组tuple(戴了紧箍咒的列表, 不能修改元素)
# 1. 元组的创建
t1 = () # 空元组
print(t1, type(t1))
t2 = (1,) # 重要(易错点):元组只有一个元素时一定要加逗号
print(t2, type(t2))
t3 = (1, 1.2, True, [1, 2, 3])
print(t3, type(t3))
# 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])
# 3. 常用方法: 元组是不可变数据类型(不能增删改)
# 查看: 通过索引和切片查看元素。 查看索引值和出现次数。
t = (1, 2, 3, 1, 1, 3)
print(t.count(1)) # 3 出现次数
print(t.index(3)) # 2 元组中的偏移量(即索引值)
四.命名元组
collections.namedtuple(typename, field_names) #typename:类名称 field_names:元组中元素的名称
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)
五.is和==的区别
is和==两种运算符在应用上的本质区别
1.Python中对象的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)
2.is和==都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同
3.==用来比较判断两个对象的value(值)是否相等;(type和value)
is也被叫做同一性运算符, 会判断id是否相同;(id, type 和value)
"""
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
# 练习
"""
编写一个云主机管理系统:
- 添加云主机(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("请输入正确的选项")
六.地址引用和深拷贝和浅拷贝
# 1. 值的引用
# 创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。(=)
nums1 = [1, 2, 3]
nums2 = nums1
nums1.append(4)
print(nums2) # 1, 2, 3, 4 两个指向同一个内存空间
# 2. 拷贝:浅拷贝和深拷贝
# 主要针对可变数据类型,如果列表中有嵌套的时候,或者列表中含有可变类型的,一定要选择深拷贝
# 2-1). 浅拷贝(副本)
#对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值。(li.copy(), copy.copy())
# 公用一个值;
# 这两个变量的内存地址一样;
# 对其中一个变量的值改变,另外一个变量的值也会改变
n1 = [1, 2, 3]
n2 = n1.copy() # n1.copy和n1[:]都可以实现拷贝。
print(id(n1), id(n2))
n1.append(4)
print(n2)
n1 = [1, 2, [1, 2]]
n2 = n1.copy()
# n1和n2的内存地址:的确拷贝了
print(id(n1), id(n2))
# n1[-1]和n2[-1]的内存地址:
print(id(n1[-1]), id(n2[-1]))
n1[-1].append(4)
print(n2)
# 2-2). 深拷贝(复制)
"""
一个变量对另外一个变量的值拷贝。(copy.deepcopy())
两个变量的内存地址不同;
两个变量各有自己的值,且互不影响;
对其任意一个变量的值的改变不会影响另外一个;
可变数据类型(可增删改的): list
不可变数据类型:数值,str, tuple, namedtuple
深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用
"""
# 2-3).copy.deepcopy()
import copy
n1 = [1, 2, [1, 2]]
n2 = copy.deepcopy(n1)
print(id(n1), id(n2))
print(id(n1[-1]), id(n2[-1]))
n1[-1].append(4)
print(n2)