Python 数据类型

数据类型简介

​ Python 的数据类型大致可分为 6 类:

  • Number(数字,布尔类型、整型、浮点型、复数等都归为数字类型)
  • String(字符串)
  • Tuple (元组)
  • List(列表)
  • Dictionary(字典)
  • Sets(集合)

这 6 种类型又可以分为 可变类型不可变类型,其中不可变类型有:Number(数字)、String(字符串)、 Tuple(元组);可变类型有:List(列表)、 Dictionary (字典)、 Sets(集合)。

不可变数据类型的变量在第一次赋值声明的时候,会在内存中开辟一块空间,用来存放这个变量被赋的值。存放这个值的内存空间就是内存中的一个地址,而这个变量实际上存储的并不是被赋予的这个值,而是存放这个值所在空间的内存地址,通过这个地址,变量就可以在内存中取出数据了。所谓不可变就是说, 我们不能改变这个数据在内存中的值,所以当我们改变这个变量的赋值时,只是在内存中重新开辟了一块空间,将这一条新的数据存放在这一个新的内存地址里,而原来的那个变量就不在引用原数据的内存地址而转为引用新数据的内存地址了。

​ 当第一次赋值声明了一个可变数据类型的时候,同样会在内存中开辟一个空间,并且将你所赋的数据值放在这块内存中,然后将这个变量指向数据所在的内存所在位置。不同的是,可变数据类型可以对内存中的数据进行修改,并且不会导致变量引用地址的变化,但是这种修改仅限于Python中的内置方法,如果要是进行重新赋值操作的话,一样会改变变量的地址指向。而当变量重新指向了新的内存之后,之前的内存也就被自动回收了。

列表

1、创建列表

1
2
3
4
5
6
7
# 方式一
name = []
print(type(name)) # 执行结果 >>> <class 'list'>

# 方式二
name = list()
print(type(name)) # 执行结果 >>> <class 'list'>

2、增(append,insert)

insert 方法用于将对象插入到列表中对应的索引位置(索引从0开始),而append方法则用于在列表末尾追加新的对象

1
2
3
4
5
6
7
name = ["cdc","ctt","cct","ttr"]

name.append('alex')
name.insert(2,'alvin')
print(name)

# 执行结果 >>> ['cdc', 'ctt', 'alvin', 'cct', 'ttr', 'alex']

3、删(remove,del,pop)

1
2
3
4
5
6
7
8
9
10
name.remove('alex')   # 删除列表中的'alex'元素 

name.remove(name[0]) # 删除列表中索引为0的元素(即第一个元素)

del name[0] # 删除列表中索引为0的元素(即第一个元素)

value = name.pop() # 弹栈删除,会默认将列表的最后一个元素删除并返回(有返回值) 
print(value)

del name # 删除整个列表

4、改

1
2
3
4
5
names_class2 = ['张三', '李四', '王五', '赵六']

names_class2[3] = '赵七'
names_class2[0:2] = ['wusir', 'alvin']
print(names_class2)

5、查

1
2
3
4
5
6
7
8
9
10
names_class2 = ['张三', '李四', '王五', '赵六']

print(names_class2[2]) # 查询索引为2的元素的值(即第三个元素)
print(names_class2[0:3]) # 查询索引值为0-3的元素的值(左闭右开)
print(names_class2[0:7])
print(names_class2[-1]) # 查询倒数第一个元素的值 print(names_class2[2:3])
print(names_class2[0:3:1]) # 查询索引值为0-3的元素的值,步长为1,即挨个查
print(names_class2[0:3:2]) # 查询索引值为0-3的元素的值,步长为2,即隔一个查一个
print(names_class2[3:0:-1]) # 从后往前查
print(names_class2[:]) # 查所有

6、其他操作

6.1 count 统计某个元素在列表中出现的次数

1
2
3
4
5
6
['to', 'be', 'or', 'not', 'to', 'be'].count('to')  # 2

x = [[1,2], 1, 1, [2, 1, [1, 2]]]
x.count(1) # 2

x.count([1,2]) # 1

6.2 extend 在列表的末尾一次性追加另一个序列中的多个值。

1
2
3
4
a = [1, 2, 3] 
b = [4, 5, 6]
a.extend(b)
print(a) # [1, 2, 3, 4, 5, 6]

extend 方法修改了被扩展的列表,而原始的连接操作(+)则不然,它会返回一个全新的列表。

1
2
3
4
5
6
7
8
a = [1, 2, 3] 
b = [4, 5, 6]
a.extend(b)
print(a) # [1, 2, 3, 4, 5, 6]

print(a + b) # [1, 2, 3, 4, 5, 6, 4, 5, 6]

print(a) # [1, 2, 3, 4, 5, 6]

6.3 index 从列表中找出第一个匹配项的索引位置

1
2
3
names_class2 = ['张三', '李四', '王五', '赵六']

names_class2.index('李四') # 1

6.4 reverse 将列表中的元素反向存放。

1
2
3
names_class2 = ['张三', '李四', '王五', '赵六']
names_class2.reverse()
print(names_class2) # ['赵六', '王五', '李四', '张三']

6.5 sort 对列表进行排序。

1
2
x = [4, 6, 2, 1, 7, 9]
x.sort() # x.sort(reverse=True) reverse参数为True表示倒序排序

6.6 拷贝

1
2
3
4
5
names = ['Alex', 'Tenglan', 'Rain', 'Tom', 'Amy', 1, 2, 3]
name_copy = names.copy()
print(name_copy)

# 执行结果 ['Alex', 'Tenglan', 'Rain', 'Tom', 'Amy', 1, 2, 3]

补充

1
2
3
b,*c=[1,2,3,4,5]
print(b) # 1
print(*c) # 2 3 4 5

元组

  • 元组被称为只读列表,即数据可以被查询,但不能被修改,所以,列表的切片操作同样适用于元组。
  • 元组写在小括号(())里,元素之间用逗号隔开。
  • 虽然tuple的元素不可改变,但它可以包含可变的对象,比如list列表。
  • 构造包含 0 个或 1 个元素的元组比较特殊,所以有一些额外的语法规则。
1
2
3
4
5
6
tup1 = ()    # 空元组
tup2 = (20,) # 一个元素,需要在元素后添加逗号
name = ('cdc','ctt','tr')
print(name[0])
print(name[1])
print(name[0:2])

字典

​ 字典是 Python 中唯一的映射类型,采用键值对(key-value)的形式存储数据。Python 对 key 进行哈希函数运算,根据计算的结果决定 value 的存储地址,所以字典是无序存储的,且 key 必须是可哈希的。可哈希表示 key 必须是不可变类型,如:数字、字符串、元组。

​ 字典(dictionary)是除列表意外python之中最灵活的内置数据结构类型。列表是有序的对象结合,字典是无序的对象集合。两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。

1、创建字典

1
2
3
4
5
dic1={'name':'alex','age':36,'sex':'male'}  # 推荐使用
dic2=dict((('name','alex'),))

print(dic1) # {'name': 'alex', 'age': 36, 'sex': 'male'}
print(dic2) # {'name': 'alex'}

2、增

1
2
3
4
5
6
7
8
9
10
11
dic3={}

dic3['name']='alex'
dic3['age']=18
print(dic3) # {'name': 'alex', 'age': 18}

# 如果键已存在,不改变键原来的值
a=dic3.setdefault('name','yuan')
b=dic3.setdefault('ages',22)
print(a,b) # alex 22
print(dic3) # {'name': 'alex', 'age': 18, 'ages': 22}

3、查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dic3={'name': 'alex', 'age': 18}

# print(dic3['name']) # alex
# print(dic3['names']) # KeyError: 'names'

# get 方法取值,如果获取不到,就是用设置的默认值
print(dic3.get('age',20)) # 18
print(dic3.get('ages',20)) # 20

print(dic3.items()) # dict_items([('name', 'alex'), ('age', 18)])
print(dic3.keys()) # dict_keys(['name', 'age'])
print(dic3.values()) # dict_values(['alex', 18])

print('name' in dic3) # py2: dic3.has_key('name'),py3 废弃
print(list(dic3.values())) # ['alex', 18]

4、改

1
2
3
4
5
6
dic3={'name': 'alex', 'age': 18}

dic3['name']='alvin'
dic4={'sex':'male','hobby':'girl','age':36}
dic3.update(dic4)
print(dic3)

5、删

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dic4={'name': 'alex', 'age': 18,'class':1}

# dic4.clear()
# print(dic4)
del dic4['name']
print(dic4)

a=dic4.popitem()
print(a,dic4)

# print(dic4.pop('age'))
# print(dic4)

# del dic4
# print(dic4)

6、其他方法

6.1 dict.fromkeys

1
2
3
4
5
6
7
8
9
10
11
# 相当于初始化,将所有键都赋同样的值
d1=dict.fromkeys(['host1','host2','host3'],'Mac')
print(d1)

d1['host1']='xiaomi'
print(d1)

d2=dict.fromkeys(['host1','host2','host3'],['Mac','huawei'])
print(d2)
d2['host1'][0]='xiaomi'
print(d2)

6.2 d.copy() 对字典 d 进行浅复制,返回一个和d有相同键值对的新字典

1
2
3
d = {"name":"cdc", "age":18}
c = d.copy()
print(c)

6.3 字典的嵌套

1
2
3
4
dic={'zhangsan':{'age':23,'sex':'male'},
'李四':{'age':33,'sex':'male'},
'wangwu':{'age':27,'sex':'women'}
}

6.4 sorted(dict) : 返回一个有序的包含字典所有key的列表

1
2
3
4
dic4 = {5:"555",2:"666",4:"444"}
print(sorted(dic4)) #根据键值来排序
print(sorted(dic4.values())) #根据值来排序
print(sorted(dic4.items())) #根据键值对来排序(按照键大小)

6.5 字典的遍历

1
2
3
4
5
6
7
8
9
10
dic5 = {"name":"cdc","age":22}

for i in dic5:
print(i,dic5[i]) #效率较高

for i in dic5.items(): #效率较低
print(i)

for i,v in dic5.items():
print(i,v)

集合

集合是一个无序的,不重复的数据组合,它的主要作用如下:

  • 去重,把一个列表变成集合,就自动去重了
  • 关系测试,测试两组数据之前的交集、差集、并集等关系
  • 把不同的元素组成一起形成集合,是python基本的数据类型。

集合元素(set elements):组成集合的成员(不可重复)

1
2
3
4
5
6
7
li=[1,2,'a','b']
s =set(li)
print(s) # {1, 2, 'a', 'b'}

li2=[1,2,1,'a','a']
s=set(li2)
print(s) #{1, 2, 'a'}

集合对象是一组无序排列的可哈希的值:集合成员可以做字典的键

1
2
3
li=[[1,2],'a','b']
s =set(li) #TypeError: unhashable type: 'list'
print(s)

集合分类:可变集合、不可变集合

可变集合(set):可添加和删除元素,非可哈希的,不能用作字典的键,也不能做其他集合的元素

不可变集合(frozenset):与上面相反

1
2
3
li=[1,'a','b']
s =set(li)
dic={s:'123'} #TypeError: unhashable type: 'set'

1、创建集合

由于集合没有自己的语法格式,只能通过集合的工厂方法set()和frozenset()创建

1
2
3
4
5
6
s1 = set('alvin')

s2= frozenset('yuan')

print(s1,type(s1)) # {'l', 'v', 'i', 'a', 'n'} <class 'set'>
print(s2,type(s2)) # frozenset({'n', 'y', 'a', 'u'}) <class 'frozenset'>

2、访问集合

由于集合本身是无序的,所以不能为集合创建索引或切片操作,只能循环遍历或使用in、not in来访问或判断集合元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
s1 = set('alvin')
print('a' in s1)
print('b' in s1)
#s1[1] #TypeError: 'set' object does not support indexing

for i in s1:
print(i)

# True
# False
# v
# n
# l
# i
# a

3、更新集合

可使用以下内建方法来更新:

  • s.add()
  • s.update()
  • s.remove()

注意:只有可变集合才能更新:

1
2
3
4
5
6
7
8
9
10
11
12
# s1 = frozenset('alvin')
# s1.add(0) #AttributeError: 'frozenset' object has no attribute 'add'

s2=set('alvin')
s2.add('mm')
print(s2) #{'mm', 'l', 'n', 'a', 'i', 'v'}

s2.update('HO')#添加多个元素
print(s2) #{'mm', 'l', 'n', 'a', 'i', 'H', 'O', 'v'}

s2.remove('l')
print(s2) #{'mm', 'n', 'a', 'i', 'H', 'O', 'v'}

4、del:删除集合本身

1
2
3
s1 = {1, 2, 3}
del s1
print(s1) # NameError: name 's1' is not defined

5、集合类型操作符

  • in ,not in
  • 集合等价与不等价(== ,!=)
  • 子集、超集
1
2
3
4
s = set('alvinyuan')
s1 = set('alvin')
print('v' in s) # True
print(s1 < s) # True
  • 联合(|)

    联合(union)操作与集合的or操作其实等价的,联合符号有个等价的方法,union()。

1
2
3
4
5
s1 = set('alvin')
s2 = set('yuan')
s3 = s1|s2
print(s3) # {'a', 'l', 'i', 'n', 'y', 'v', 'u'}
print(s1.union(s2)) # {'a', 'l', 'i', 'n', 'y', 'v', 'u'} 
  • 交集(&)

与集合and等价,交集符号的等价方法是intersection()

1
2
3
4
5
6
s1 = set('alvin')
s2 = set('yuan')
s3 = s1 & s2
print(s3) # {'n', 'a'}

print(s1.intersection(s2)) # {'n', 'a'}
  • 差集(-)

等价方法是difference()

1
2
3
4
5
6
s1 = set('alvin')
s2 = set('yuan')
s3 = s1 - s2
print(s3) # {'v', 'i', 'l'}

print(s1.difference(s2)) # {'v', 'i', 'l'} 
  • 对称差集(^)

对称差分是集合的XOR(‘异或’),取得的元素属于 s1,s2 但不同时属于 s1 和 s2 。其等价方法symmetric_difference()

1
2
3
4
5
6
s1 = set('alvin')
s2 = set('yuan')
s3 = s1 ^ s2
print(s3) #{'l', 'v', 'y', 'u', 'i'}

print(s1.symmetric_difference(s2)) #{'l', 'v', 'y', 'u', 'i'}
  • 应用
1
2
3
4
5
6
7
8
9
10
11
# 最简单的去重方式
lis = [1,2,3,4,1,2,3,4]
print list(set(lis)) #[1, 2, 3, 4]

# 难度升级,列表去重后保持原来的顺序
original_lis = [1, 2, 5, 3, 1, 2]
lis = list(set(original_lis))
print(lis) # [1, 2, 3, 5]

lis.sort(key=lambda x: original_lis.index(x))
print(lis) # [1, 2, 5, 3]

深浅拷贝

​ Python中,对象的赋值、拷贝(深/浅拷贝)之间是有差异的,其实这个是由于共享内存导致的结果。拷贝原则上就是把数据分离出来,复制其数据,并以后修改互不影响。

  • 普通赋值,数据完全共享

​ 赋值是在内存中指向同一个对象,如果是可变类型,比如列表,修改其中一个,另一个必定改变,如果是不可变类型,比如字符串,修改了其中一个,另一个并不会变。

1
2
3
4
5
6
7
8
lis_1 = [1, 2, ["a", "b", "c"], 4]
lis_2 = lis_1

lis_1[0] = 1111
lis_1[2][1] = "bbbbb"

print(lis_1) # [1111, 2, ['a', 'bbbbb', 'c'], 4]
print(lis_2) # [1111, 2, ['a', 'bbbbb', 'c'], 4]
  • 浅拷贝,数据半共享

    复制其数据独立内存存放,但是只拷贝成功第一层,即最里面一层。

1
2
3
4
5
6
7
8
9
10
import copy

lis_1 = [1, 2, ["a", "b", "c"], 4]
lis_3 = copy.copy(lis_1)

lis_1[0] = 1111
lis_1[2][1] = "bbbbb"

print(lis_1) # [1111, 2, ['a', 'bbbbb', 'c'], 4]
print(lis_3) # [1, 2, ['a', 'bbbbb', 'c'], 4]
  • 深拷贝,数据完全不共享

    复制其数据完完全全放独立的一个内存,完全拷贝,数据不共享

1
2
3
4
5
6
7
8
9
10
import copy

lis_1 = [1, 2, ["a", "b", "c"], 4]
lis_4 = copy.deepcopy(lis_1)

lis_1[0] = 1111
lis_1[2][1] = "bbbbb"

print(lis_1) # [1111, 2, ['a', 'bbbbb', 'c'], 4]
print(lis_4) # [1, 2, ['a', 'b', 'c'], 4]

Python 数据类型
https://clark-cdc.github.io/2019/03/16/0003-基本数据类型/
作者
clark
发布于
2019年3月16日
许可协议