首页 > 技术文章 > 04 python开发之数据类型

caojiaxin 2020-12-02 10:25 原文

04 python开发之数据类型

4 数据类型

4.1 概述

4.1.1 基本概念

  • 不同种类的数据存取机制不一样,用途也不一样

  • 数据是事物的状态,事物的状态是分为多种多样的,对应着就应该用不同类型的数据去记录。

  • 具体什么场景用什么类型

  • 有以下6种类型:

    整型 int

    浮点型 float

    字符串 str

    列表类型 list

    字典类型 dict

    布尔类型 bool

4.1.2 整型int

  • 作用:记录年龄、等级、号码、个数...

  • 定义:用整数表示变量的值

age = 18			# age=int(18)
number = 23			# number=int(23)
print(age,type(age))            # type查看数据类型

4.1.3 浮点型float

  • 作用:记录身高、体重、薪资...

  • 定义:用小数表示变量的值

salary = 3.3	 # salary=float(3.3)
height = 1.7	 # height=float(1.7)

4.1.4 字符串str

  • 作用:记录描述性质的内容,如名字、国籍、爱好、一段话...

  • 定义:用''或""或""" """或''' '''中间包含一系列字符

单行:''、""
多行:''''''、""""""
msg1 = 'hello yue'
msg2 = "hello yyy"
msg3 = """
1111
2222
3333
"""
msg4 = '''
44444
55555
66666
'''
# 外层双引号,内层就要用单引号
print("my name is 'ccc'")

4.1.5 列表类型list

  • 作用:按照顺序存放多个值,并且可以按照顺序取出指定的值

  • 定义:在[]内用逗号分隔开多个任意类型的值,列表可以套多个列表

正向取值
#      0   1   2            3
#		      0     1        2  
# 				   0   1
L = [111,3.4,'abc',['xxx','www',[333,4444]]]
print(L[0])  		# 输出:111(索引从0开始)
反向取值
print(L[-1])	              # 输出: ['xxx', 'wwww', [333, 444]]
print(L[-3])	              # 3.4
print(l[-1][2][0])	      # 333

4.1.6 字典类型dict

  • 作用:按照属性存放多个值,key:value组合

  • 定义:在{}内用逗号分隔开多个key:value,key通常是str类型,value可以是任意类型

info = {
    "name": "ccc",
    "age": 18,
    "gender": "male",
    "annual_salary": 18,
    "level": 10
}

# 输入查找条件,按照键值对取值
print(info['age'])		# 输出:18
# 字典嵌套
# 例
d = {"k1": 111, "k2": 222, "k3": [444, 555], "k4": {"a": 1, "b": 2}}
print(d["k3"][0])		# 输出:444
print(d["k4"]["a"])		# 输出:1

4.1.7 布尔类型bool

  • 作用:True和False,通常用作条件,用于判断

  • 定义:tag = True或tag = False

# 显式的布尔值
tag = True
tag = False
# 隐式的布尔值
# 所有数据类型的值都可以作为隐式布尔值使用
# 其中0、空、None三者的布尔值为False,其余均为True

# print(bool(1))		# True
# print(bool(0))		# False
# print(bool([]))		# False
# print(bool(""))		# False
# print(bool(""))		# False
# print(bool({}))		# False
# print(bool(None))		# False
x = True
y = False
print(type(x))		# bool

x = None
print(x is None)	# True

4.2 可变与不可变类型

4.2.1 可变类型(不可hash类型)

  • 值改变的情况下,内存地址/id不变

  • 证明改变的就是原值,即可变类型

l = [111, 222]
print(id(l))	# 2725287619456
l[0] = 3333
print(id(l))	# 2725287619456

4.2.2 不可变类型(可hash类型)

  • 值改变的情况下,内存地址也变

  • 证明产生了新的值,即原值不可变

x = 10
print(id(x))	# 140708016953280
x = 12
print(id(x))	# 140708016953344

4.3 数字类型常用操作及内置方法

4.3.1 整型及浮点型

  • 整型int

1、用途:年龄、等级、号码...

2、定义方式:

​ age = 18 # age = int(18)

3、数据类型转换

​ x = int(" 103 ") # 把纯数字组成的字符串转换成int类型(前后的空格可消,中间有会报错)

​ print(x, type(x)) # 103 <class 'int'>

  • 浮点型float

1、用途:身高、体重、薪资...

2、定义方式:

​ salary = 3.3 # salary = float(3.3)

3、数据类型转换

​ x = float(" 3.3 ")

​ print(x, type(x)) # 3.3 <class 'float'>

4.3.2 其他数字类型(了解)

  • 长整型long

在python2中(python3中没有长整形的概念):      
>>> num=2L
>>> type(num)
<type 'long'>

  • 复数

>>>x=1-2j
>>>x.real
1.0
>>>x.imag
-2.0 

4.3.3 常用操作及内置方法

  • 整型int

    + - * / % > <= // **

  • 浮点型float

    + - * / % > <= // **

4.3.4 总结

  • 整型int

只能存一个值

不可变

  • 浮点型float

只能存一个值

不可变

4.3.5 补充:进制

  • 十进制 : 0 1 2 3 4 5 6 7 8 9

    二进制 : 0 1

    八进制 : 0 1 2 3 4 5 6 7

    十六进制:0 1 2 3 4 5 6 7 8 9 a b c d e f

  • 命令操作

    print(bin(11)) # 十进制转二进制
    print(oct(11)) # 十进制转八进制
    print(hex(11)) # 十进制转十六进制

    print(int("11", 2)) # 二进制转十进制
    print(int("11", 8)) # 八进制转十进制
    print(int("11", 16)) # 十六进制转十进制

  • 自由计算

    十进制<---二进制
    1011
    1*2^3 + 0*2^2 + 1*2^1 + 1*2^0
      8   +   0   +   2   +   1   = 11
    十进制<---八进制
    1011
    1*8^3 + 0*8^2 + 1*8^1 + 1*8^0
     512  +   0   +   8   +   1   = 521
    十进制<---十六进制
    1011
    1*16^3 + 0*16^2 + 1*16^1 + 1*16^0
     4096  +    0   +   16   +   1   = 4113
    
    十进制--->二进制(除二取余)
    11
    11/2=5-1
    5/2=2-1
    2/2=1-0
    最终得到1011
    
    十进制--->八进制(除八取余)
    十进制--->十六进制(除十六取余)
    

4.4 字符串类型常用操作及内置方法

4.4.1 概述

  • 用途:记录一些描述性质的内容,如国籍、名字、一段话...

  • 定义方式:

    msg = "abc" # msg = str("abc")

  • 数据类型转换:

    res = str(111) # 可以把所有类型都转换成str类型

    print(res, type(res)) # 111 <class 'str'>

4.4.2 常用操作及内置方法(*****)

  • 按索引取值(正向取+反向取):只能取

  • 切片(顾头不顾尾,步长)

  • 长度len

  • 成员运算in和not in

  • 移除空白strip

  • 切分split

  • 循环

# 按索引取值(正向取+反向取):只能取
msg = "hello world"
print(msg[0])
msg[0] = "H"  					# 报错,不能改

# 切片(顾头不顾尾,步长)
msg = "hello world"
print(msg[3:5])					# lo
print(msg[3:8:2])				# l o
print(msg[-1:2:-2])				# drwo
print(msg[::2])					#hlowrd
print(msg[-1::-1])				# dlrow olleh

# 长度len:统计的是字符个数
msg = "h e你"
print(len(msg))					# 4(一个空格、一格中文字符都是一个字符)

# 成员运算in和not in
msg = "hello world"
print("he" in msg)       		# True
print("d" in msg)        		# True
print("hd" in msg)       		# False
print("hd" not in msg)   		# True

# 移除空白strip(只会移除两边,不会移除内部)
name = "          cc c       "
print(name.strip())       		# cc c
print(name)               		#           cc c
name = "**********ccc***********"
print(name.strip("*"))     		# ccc
x = "*-/+()=abc*(-)/*"
print(x.strip("-+*/(=)"))   	        # abc

name = input("username>>>:").strip()
pwd = input("password>>>:").strip()
if name == "ccc" and pwd == "123":
    print("ok")
else:
    print("error")

# 切分split
info = "root: 123: 2: 0"
res = info.split(":", 1)
print(res[0])
print(res)

# 循环
msg = "hello"
for i in msg:
    print(i)

4.4.3 常用操作及内置方法(****)

  • strip移除空白,lstrip移除左边空白,rstrip移除右边空白

  • lower全小写输出,upper全大写输出

  • startswith判断是否以什么开头,endswith判断是否以什么结尾

  • format

  • split切分,rsplit

  • jion用一个字符把列表连在一起

  • replace替代

  • isdigit判断是否为整型

1、strip移除两边空白、lstrip移除左边空白、rstrip移除右边空白
name = "*egon**"
print(name.strip('*'))
print(name.lstrip('*'))
print(name.rstrip('*'))

2、lower全小写输出、upper全大写输出
name = '*eGon**'
print(name.lower())
print(name.upper())

3、判断是否以什么开头startswith或结尾endswith
name = 'alex_SB'
print(name.endswith('SB'))
print(name.startswith('alex'))

4、format三种玩法
字符串格式化
方式1
res = "my name is %s my age is %s" % ("egon", 18)
print(res)
方式2
res = '{} {} {}'.format('egon', 18, 'male')
res = '{1} {0} {1}'.format('egon', 18, 'male')
res = '{name} {age} {sex}'.format(sex='male', name='egon', age=18)
print(res)
======================format
套用字典.format(**字典))
kwargs = {'name': "ccc", 'age': 18}
print('我的名字是{name},我的年龄是{age}'.format(**kwargs))
套用列表.format(*列表))
l = [111, 222]
print('我的名字是{},我的年龄是{}'.format(*l))
对齐
res = "my name is {} my age is {}".format("ccc", 18)
res = "my name is {0:*<10} my age is {1}".format("ccc", 18)
res = "my name is {0:@>10} my age is {1}".format("ccc", 18)
res = "my name is {0:-^10} my age is {1:=^10}".format("ccc", 18)
print(res)
进制与精度b二进制、o十进制、x十六进制、,科学输出、.3f保留三位小数四舍五入
res = "my name is {0} my age is {1:b}".format("ccc", 18)
res = "my name is {0} my age is {1:o}".format("ccc", 18)
res = "my name is {0} my age is {1:x}".format("ccc", 18)
res = "my name is {0} my age is {1:,}".format("ccc", 180000000000)
res = "my name is {0} my age is {1:.3f}".format("ccc", 6.666666)
print(res)
======================f""
name = "egon"
age = 18
res = f"my name is {name} my age is {age}"
print(res)

5、切分.split('分隔符')
name = 'root:x:0:0::/root:/bin/bash'
print(name.split(':'))
print(name.split('/'))
name = 'C:/a/b/c/d.txt'
print(name.split('/'))
name = 'a|b|c'
print(name.rsplit('|', 1))

6、join用一个字符把列表连在一起(列表内都是字符串)
tag = '/'
print(tag.join(['egon', 'say', 'hello', 'world']))
l = ["1111", "2222", "3333"]
res = ':'.join(l)
print(res)

7、replace替换
name = 'alex say : i have one tesla, my name is alex'
print(name.replace('alex', 'SB'))

8、isdigit判断是否是整型
print("abc".isdigit())
print("  123 ".isdigit())
print("123".isdigit())

age = input("your age:").strip()
if age.isdigit():
    age = int(age)
    if age > 18:
        print("too old")
    elif age < 18:
        print("too young")
    else:
        print("you got it")
else:
    print("You have to enter a number")

了解部分
name = 'egon say hello'
print(name.find('1', 1, 3))
print(name.find('on'))
print(name.index('1', 1, 3))
print(name.count('e', 6,))

name = 'egon'
print(name.center(10, '-'))
print(name.ljust(10, '+'))
print(name.rjust(10, '@'))
print(name.zfill(10))

name = 'egon\thello'
print(name)
print(name.expandtabs(2))

name = "egOn"
print(name.capitalize())        # Egon
print(name.swapcase())          # EGoN
msg = 'egon say hi'
print(msg.title())              # Egon Say Hi

is数字系列
num1 = b'4'
num2 = u'4'
num3 = '四'
num4 = 'Ⅳ'

.isdigit判断bytes、unicode
print(num1.isdigit())       # True
print(num2.isdigit())       # True
print(num3.isdigit())       # False
print(num4.isdigit())       # False

.isdecimal判断unicode
print(num2.isdecimal())       # True
print(num3.isdecimal())       # False
print(num4.isdecimal())       # False

.isnumeric判断unicode、中文、罗马
print(num2.isnumeric())       # True
print(num3.isnumeric())       # True
print(num4.isnumeric())       # True

is其他
print('===>')
name = 'egon123'
print(name.isalnum())  # 字符串由字母或数字组成
print(name.isalpha())  # 字符串只由字母组成

print(name.isidentifier())
print(name.islower())
print(name.isupper())
print(name.isspace())
print(name.istitle())

4.4.4 总结

  • 只能存一个值

  • 是有序的

  • 不可变

4.5 列表类型常用操作及内置方法

4.5.1 概述

  • 用途:按照位置记录多个值---->索引对应值

  • 定义方式:在[]内用逗号分隔开多个任意类型的值

    l = [111, 11.11, "aaa", [222, 333]] # l = list(...)

  • 数据类型转换:

    print(list("hello")) # ['h', 'e', 'l', 'l', 'o']

    print(list({'k1': 111, 'k2': 222})) # ['k1', 'k2']

    print(list(range(5))) # [0, 1, 2, 3, 4]

4.5.2 常用操作及内置方法(*****)

  • 按照索引取值(正向取+反向取):可改可取

  • .append()追加

  • .insert()插入

  • .remove, .pop, del删除

  • 切片

  • len长度

  • 成员运算in和not in

  • 循环

# 按索引存取值(正向取+反向取):可改可取
l = ["aaa", "bbb", 111]
print(l[0])				# aaa
print(l[-1])				# 111
print(id(l))				# 2724827099008
l[0] = "xxx"
print(l)				# ['xxx', 'bbb', 111]
print(id(l))				# 2724827099008
l[3] = "ccc"				# 报错list assignment index out of range

# 追加
l = ["aaa", "bbb", 111]
l.append("ddd")				# 不会有任何返回值
print(l)				# ['aaa', 'bbb', 111, 'ddd']
l.append("eee")				# 在最后面追加
print(l)				# ['aaa', 'bbb', 111, 'ddd', 'eee']

# 插入
l = ["aaa", "bbb", 111]
res = l.insert(1, "qqq")	        # 在位置前加
print(l)				# ['aaa', 'qqq', 'bbb', 111]
print(res)				# None

# 删除
l = ["aaa", "bbb", 111]
# Ⅰ 万能删除
del l[0]
print(l)				# ['bbb', 111]
# Ⅱ l.remove指定元素删除
res = l.remove(111)
print(l)				# ['aaa', 'bbb']
print(res)				# 没有返回值None
# Ⅲ l.pop指定索引删除,会有返回值,返回的是删除的元素
res = l.pop(0)
print(l)				# ['bbb', 111]
print(res)				# aaa

# 切片(顾头不顾尾,步长)
l = [111, 222, 333, 444, 555, 666, 777]
print(l[0:5])				# 0 1 2 3 4
print(l[0:5:2])				# 0 2 4
print(l[:])				# 拷贝到新列表
print(l[::-1])				# 反向

# 长度
l = [111, 222, 333, 444, 555, 666, 777]
print(len(l))				# 7

成员运算in和not in
l = [111, 222, 333, 444, 555, 666, 777]
print(111 in l)				# True
print(000 not in l)     	        # True

# 循环
l = [111, 222, 333, 444, 555, 666, 777]
for i in l:
    print(i)

4.5.3 常用操作及内置方法(****)

  • .count()计数

  • .extend()追加

  • .reverse()反向

  • .index()区间计数,没有就报错

  • .clear()清空

  • .sort()排序

  • .copy()拷贝

# .count计数
l = [111, 222, 111, 444]
print(l.count(111))			# 2

# .extend追加
l = [111, 222, 111, 444]
l.extend('hello')
l.extend("xxx", "yyy")                  # 报错
print(l)				# [111, 222, 111, 444, 'h', 'e', 'l', 'l', 'o']

# .reverse反向
l = [111, 222, 111, 444]
res = l.reverse()			# 没有输出
print(l)				# [444, 111, 222, 111]
print(res)				# None

# .index
l = [111, 222, 111, 444]
print(l.index(111, 1, 3))               # 2 区间计数
print(l.index("xxx", 1, 5))             # 没有就报错

# .clear
l = [111, 222, 111, 444]
l.clear()
print(l)			        # [] 清空

# .sort排序
# l = [3, -1, 4, 9.9, 7]
# l.sort()                		# 从小到大
# l.sort(reverse=True)    		# 从大到小
# print(l)			        # [9.9, 7, 4, 3, -1]
# l = [3, -1, 4, 9, 7, "x"]		# 不能有字符串,只能是数字型

# .copy
res1 = l.copy()				# 浅拷贝
res2 = l[:]			        # 浅拷贝
print(res1)
print(res2)
======================浅拷贝
l1 = ["china", 333, [300, 100]]
l2 = l1.copy()
print(l1)					# ['china', 333, [300, 100]]
print(l2)					# ['china', 333, [300, 100]]
l1[2][0] -= 100
print(l1)					# ['china', 333, [200, 100]]
print(l2)					# ['china', 333, [200, 100]]
print(id(l1[0]), id(l1[1]), id(l1[2]))		# 2806369619312 2806368532944 2806371052288
print(id(l2[0]), id(l2[1]), id(l2[2]))		# 2806369619312 2806368532944 2806371052288
l1[0] = 'xxx'
print(l1)					# ['xxx', 333, [300, 100]]
print(l2)					# ['china', 333, [300, 100]]
print(id(l1[0]), id(l1[1]), id(l1[2]))		# 1971974639152 1971973552592 1971976072064
print(id(l2[0]), id(l2[1]), id(l2[2]))		# 1971974639152 1971973552592 1971976072064
l1[2][0] = 400
print(l1)					# ['china', 333, [400, 100]]
print(l2)					# ['china', 333, [400, 100]]
浅拷贝指向第一层,不管是不是列表都只复制一层
第一层数据如果是不可变的,l2就不会变id相应会不同,可变就一起变

======================深拷贝
from copy import deepcopy
l1 = ["china", 333, [300, 100]]
l2 = deepcopy(l1)
print(id(l1[0]), id(l1[1]), id(l1[2]))		# 2067178917360 2067177830864 2067181408384
print(id(l2[0]), id(l2[1]), id(l2[2]))		# 2067178917360 2067177830864 2067181408960
l1[0] = "xxx"
l1[1] = "yyy"
l1[2][0] = 400
print(l1)					# ['xxx', 'yyy', [400, 100]]
print(l2)					# ['china', 333, [300, 100]]
深拷贝遇到列表等可变类型时,id就会不一样
深拷贝不会随不可变数据改变而改变
深拷贝是重新分配一块内存,将原数据以递归方式拷贝到新对象中
新对象和原对象没有任何关联

4.5.4 总结

  • 可以存多个值

  • 有序

  • 可变

4.5.5 补充:队列与堆栈

  • 队列:FIFO先进先出
l = []
入队列
l.append("first")
l.append("second")
l.append("third")
print(l)			# ['first', 'second', 'third']
出队列
print(l.pop(0))			# first
print(l.pop(0))			# second
print(l.pop(0))			# third
  • 堆栈:LIFO后进先出
l = []
入栈
l.append("first")
l.append("second")
l.append("third")
print(l)			# ['first', 'second', 'third']
出栈
print(l.pop())			# third
print(l.pop())			# second
print(l.pop())			# first

4.6 元组类型常用操作及内置方法

4.6.1 概述

  • 用途:按照位置存放多个值,索引对应值

  • 定义方式:在()内用逗号分隔开多个任意类型的值

    l = (11, 11.11, "aaa", [222, 333]) # l = tuple(...)

    print(l[-1][0]) # 222

    l[0] = 111 # 报错

  • 数据类型转换:

    print(tuple('hello')) # ('h', 'e', 'l', 'l', 'o')

    t = (111, )

    print(type(l)) # <class 'tuple'>

4.6.2 常用操作及内置方法(*****)

  • 按索引取值(正向取+反向取):只能取

  • 切片(顾头不顾尾,步长)

  • 长度

  • 成员运算in和not in

  • 循环

tuple = (1, "hahah", 12.21, 25, 33)
# 按索引取值(只能取)
print(tuple[0])			# 1
print(tuple[-1])		# 33
tuple[-1] = 55			# 报错

# 切片
print(tuple[0:5:2])		# (1, 12.21, 33)

# 长度
print(len(tuple))		# 5

# 成员运算
print("hahah" in tuple)	# True
print(45 not in tuple)	# True

# 循环
for line in tuple:
    print(line)
# 1
# hahah
# 12.21
# 25
# 33

4.6.3 常用操作及内置方法(****)

t = (11, 222, 333, 222)
print(t.index(333))           # 在元组内就显示在第几个
print(t.index(223332232))     # 不在元组内直接报错
print(t.count(333))           # 计数

4.6.4 总结

  • 可以存多个值
  • 有序
  • 不可变

4.6.5 元组特殊情况

t = (11, 22, ["xx", "yy"])
print(id(t[0]), id(t[1]), id(t[2]))		# 140707921795040 140707921795392 1700891389888
# t[0] = 11111          # 报错
# t[2] = 11111          # 报错
t[2][0] = "xxx"
print(t)					# (11, 22, ['xxx', 'yy'])
print(id(t[0]), id(t[1]), id(t[2]))		# 140707921795040 140707921795392 1700891389888
# 元组内列表数据可变,但id不变

4.7 字典类型常用操作及内置方法

4.7.1 概述

  • 用途:存多个值,key:value存取,存取速度快

  • 定义方式:在{}内用逗号分隔开多个key:value,key必须是不可变类型,通常是字符串类型,value可以是任意类型的值

    info = {'name': 'egon', 'age': 18, 'gender': 'male'} # info = dict({...})

    key不能重复,只会显示最后赋给它的值

  • 数据类型转换:

    info = dict(name = 'egon', age = 18, gender = 'male')

    print(info) # {'name': 'egon', 'age': 18, 'gender': 'male'}

    info = dict([['name', 'egon'], ('gender', 18)])

    print(info) # {'name': 'egon', 'gender': 18}

    res = {}.fromkeys(('name', 'age', 'gender'), None)

    print(res) # {'name': None, 'age': None, 'gender': None}

    l = {} # 花括号内是空字典

    print(l, type(l)) # {} <class 'dict'>

4.7.2 常用操作及内置方法(*****)

  • 按key取值:可存可取

  • 长度len

  • 成员运算in和not in

  • 删除

  • 键keys(),值values(),键值对items()

  • 循环

1、按key存取值:可存可取
d = {"k1": 111, "k2": 222, "k3": 333}
d["k1"] = 666
print(d)              # {'k1': 666, 'k2': 222, 'k3': 333}
d["k4"] = 999
print(d)              # {'k1': 111, 'k2': 222, 'k3': 333, 'k4': 999}

2、长度len
d = {"k1": 111, "k2": 222, "k3": 333}
print(len(d))         # 3

3、成员运算in和not in
字典依据key运算
d = {"k1": 111, "k2": 222, "k3": 333}
print('k1' in d)      #True
print(111 in d)       # False

4、删除
d = {"k1": 111, "k2": 222, "k3": 333}
方式一
del d['k1']
print(d)              # {'k2': 222, 'k3': 333}
方式二
res = d.pop('k1')
print(res)            # 111 有返回值(随机删)
print(d)              # {'k2': 222, 'k3': 333}

5、键keys(),值values(),键值对items()
d = {"k1": 111, "k2": 222, "k3": 333}
在python2中
>>> d = {"k1": 111, "k2": 222, "k3": 333}
>>> d.keys(),type(d.keys())
(['k3', 'k2', 'k1'], <type 'list'>)
>>> d.values(),type(d.values())
([333, 222, 111], <type 'list'>)
>>> d.items(), type(d.items())
([('k3', 333), ('k2', 222), ('k1', 111)], <type 'list'>)

在python3中
print(d.keys(), type(d.keys()))         # dict_keys(['k1', 'k2', 'k3']) <class 'dict_keys'>
print(d.values(), type(d.values()))     # dict_values([111, 222, 333]) <class 'dict_values'>
print(d.items(), type(d.items()))       # ('k2', 222), ('k3', 333)]) <class 'dict_items'>

6、循环
只取key
for i in d.keys():
    print(i)
只取value
for i in d.values():
    print(i)
value与key对应
方法一
for i in d:
    print(i, d[i])
方法二
for x, y in d.items():
    print(x, y)

4.7.3 常用操作及内置方法(****)

d = {"k1": 111, "k2": 222, "k3": 333}

dic = d.copy()
print(dic)          # {'k1': 111, 'k2': 222, 'k3': 333}

d.update({'k3': 4646, 'k4': 6666})
print(d)            # {'k1': 111, 'k2': 222, 'k3': 4646, 'k4': 6666}

res = d.popitem()   # 删除最后一个值,LIFO后进先出
print(res)          # ('k3', 333)
print(d)            # {'k1': 111, 'k2': 222}

d = {"k2": 222, "k3": 333}
if 'k1' not in d:
    d['k1'] = 66666666666
res = d.setdefault('k1', 6666666666)    # 两者都可以达成
print(res)         # 66666666666 k1不存在的情况下添加
print(d)           # {'k2': 222, 'k3': 333, 'k1': 66666666666}

4.7.4 总结

  • 可以存多个值

  • 无序

  • 可变

    d = {"k1": 1111}

    print(id(d)) # 1844777596544

    d['k1'] = 2222

    print(id(d)) # 1844777596544

4.7.5 练习

=======================练习1
# 有如下值集合 [11,22,33,44,55,66,77,88,99,90]
# 将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中
# 即: {'k1': 大于66的所有值, 'k2': 小于66的所有值}
nums = [11, 22, 33, 44, 55, 66, 77, 88, 99]
d = {'k1': [], 'k2': []}
for num in nums:
    if num > 66:
        d['k1'].append(num)
    else:
        d['k2'].append(num)
print(d)                # {'k1': [77, 88, 99], 'k2': [11, 22, 33, 44, 55, 66]}

=======================练习2
统计s='hello alex alex say hello sb sb'中每个单词的个数
结果如:{'hello': 2, 'alex': 2, 'say': 1, 'sb': 2}
s = 'hello alex alex say hello sb sb'
words = s.split()
d = {}
for x in words:
    if x not in d:
        d[x] = 1
    else:
        d[x] += 1
print(d)                # {'hello': 2, 'alex': 2, 'say': 1, 'sb': 2}

d.get()

4.8 集合类型常用操作及内置方法

4.8.1 概述

  • 作用:去重,关系运算

  • 回顾:可变类型是不可hash类型,不可变类型是可hash类型

  • 定义方式:在{}内用逗号分隔开多个不可变类型的值

    Ⅰ 每个元素必须是不可变类型(可hash,可作为字典的key)

    Ⅱ 集合内元素唯一

    Ⅲ 集合内元素无序

    • 集合的目的不是将不同的值存放到一起
    • 不同的集合间来做关系运算,无需纠结集合中单个值

    s = {111, 111, 3.3, "aaa", 3.3, (111, 222)} # s = set(...)

    print(s) # {(111, 222), 3.3, 'aaa', 111}

  • 数据类型转换:

    res = set('hello')

    print(res, type(res)) # {'h', 'e', 'l', 'o'} <class 'set'>

4.8.2 常用操作及内置方法(*****)

  • 长度len

  • 成员运算in和not in

  • 关系运算

1、长度len
s = {111, 222, 333}
print(len(s))           # 3

2、成员运算in和not in
s = {111, 222, 333}
print(111 in s)         # True
print(11 not in s)      # True
=====================关系运算
pythons = {'alex', 'egon', 'yuanhao', 'wupeiqi', 'gangdan', 'biubiu'}
linuxs = {'wupeiqi', 'oldboy', 'gangdan'}
3、|合集
print(pythons | linuxs)               # 方法一
print(pythons.union(linuxs))          # 方法二
# {'yuanhao', 'egon', 'wupeiqi', 'gangdan', 'biubiu', 'oldboy', 'alex'}

4、&交集:共同部分
print(pythons & linuxs)               # 方法一
print(pythons.intersection(linuxs))   # 方法二
# {'gangdan', 'wupeiqi'}

# 将交集更新给pythons
pythons = pythons & linuxs            # 方法一
pythons.intersection_update(linuxs)   # 方法二
print(pythons)
# {'wupeiqi', 'gangdan'}

5、-差集
# pythons有而linuxs没有
print(pythons - linuxs)               # 方法一
print(pythons.difference(linuxs))     # 方法二
# {'alex', 'biubiu', 'yuanhao', 'egon'}

# linuxs有而pythons没有
print(linuxs - pythons)               # 方法一
print(linuxs.difference(pythons))     # 方法二
# {'oldboy'}

6、^对称差集:取出pythons有或linuxs有的
res = pythons ^ linuxs                            # 方法一
print(res)
res = pythons.symmetric_difference(linuxs)        # 方法二
print(res)
res = (pythons - linuxs) | (linuxs - pythons)     # 繁琐
print(res)
res = (pythons | linuxs) - (pythons & linuxs)     # 繁琐
print(res)
# {'alex', 'yuanhao', 'biubiu', 'egon', 'oldboy'}

7、==
s1 = {1, 2, 3}
s2 = {3, 2, 1}
print(s1 == s2)         	# True

8、父集:>,>=
9、子集:<,<=
s1 = {1, 2, 3, 4, 5}
s2 = {3, 2, 1}
print(s1 >= s2)                # True
print(s1 <= s2)                # False

4.8.3 常用操作及内置方法(****)

  • .update 更新

  • .pop 随机删

  • .remove 具体删掉某一值

  • .discard 删掉不存在的值会报错,remove不会

  • .add 添加值,位置随机,因为集合无序

  • .isdisjoint 判断两个集合是否包含相同的元素

.update 更新
s = {"aaa", 22, 3.3, "bbb"}
s.update({22, 3, 4, 5})
print(s)                    # {3.3, 3, 4, 5, 'aaa', 'bbb', 22}

.pop 随机删
s = {"aaa", 22, 3.3, "bbb"}
res = s.pop()
print(res)                  # 3.3 有输出结果,随机删
print(s)                    # {'bbb', 'aaa', 22}

.remove 具体删掉某一个值
s = {"aaa", 22, 3.3, "bbb"}
res = s.remove("bbb")
print(res)                  # None 没有输出结果
print(s)                    # {'aaa', 3.3, 22}

.discard 删不存在的值会报错,remove不会
s = {"aaa", 22, 3.3, "bbb"}
s.discard("ccc")            # 没有该值会直接报错
print(s)
s.remove("ccc")             # 没有该值不会报错,返回原值
print(s)                    # {'aaa', 3.3, 22, 'bbb'}

.add 添加值,位置随机,因为集合无序
s = {"aaa", 22, 3.3, "bbb"}
s.add("ccc")
print(s)                    # {3.3, 'aaa', 'ccc', 22, 'bbb'}

isdisjoint 判断两个集合是否包含相同的元素
s1 = {1, 2, 3}
s2 = {4, 5, 6, 3}
print(s1.isdisjoint(s2))    # False

4.8.4 总结

  • 可以存多个值

  • 无序

  • 可变

    s = {1, 2, 3}

    print(id(s)) # 2189058917984

    s.add(4)

    print(id(S)) # 2189058917984

4.8.5 练习

# ==========================练习1
# 有如下列表,列表元素为不可hash类型,去重,得到新列表,
# 且新列表一定要保持列表原来的顺序
# l=[
#     {'name':'egon','age':18,'sex':'male'},
#     {'name':'alex','age':73,'sex':'male'},
#     {'name':'egon','age':20,'sex':'female'},
#     {'name':'egon','age':18,'sex':'male'},
#     {'name':'egon','age':18,'sex':'male'},
# ]
l = [
    {'name': 'egon', 'age': 18, 'sex': 'male'},
    {'name': 'alex', 'age': 73, 'sex': 'male'},
    {'name': 'tony', 'age': 20, 'sex': 'female'},
    {'name': 'egon', 'age': 18, 'sex': 'male'},
    {'name': 'egon', 'age': 18, 'sex': 'male'},
]
res = []
for item in l:
    if item not in res:
        res.append(item)
print(res)
# [{'name': 'egon', 'age': 18, 'sex': 'male'},
# {'name': 'alex', 'age': 73, 'sex': 'male'},
# {'name': 'tony', 'age': 20, 'sex': 'female'}]  # 三行同一行

4.9 数据类型总结

4.9.1 按照存储空间的占用分(低到高)

​ 数字

​ 字符串

​ 集合:无序,无需存索引相关信息

​ 元组:有序,需要存索引相关信息,不可变

​ 列表:有序,需要存索引相关信息,可变,需要处理数据的增删改

​ 字典:无序,需要存key和value映射的相关信息,可变,需要处理数据的增删改

4.9.2 按存储个数区分

​ Ⅰ 标量/原子类型 数字、字符串

​ Ⅱ 容器类型 列表、元组、字典

4.9.3 按可变不可变区分

​ Ⅰ 可变 列表、字典

​ Ⅱ 不可变 数字、字符串、元组

4.9.4 按访问顺序区分

​ Ⅰ 直接访问 数字

​ Ⅱ 顺序访问(序列类型) 字符串、列表、元组

​ Ⅲ key值访问(映射类型) 字典

推荐阅读