python基础三(数据类型)

一 引子

1 什么是数据?

  x=10,10是我们要存储的数据

2 为何数据要分不同的类型

  数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示

3 数据类型

  数字(整形,长整形,浮点型,复数)

  字符串

  字节串:在介绍字符编码时介绍字节bytes类型

  列表

  元组

  字典

  集合

4 按照以下几个点展开数据类型的学习

#======================================基本使用======================================
#1、用途

#2、定义方式

#3、常用操作+内置的方法

#======================================该类型总结====================================
#存一个值or存多个值
    
#有序or无序

#可变or不可变(1、可变:值变,id不变。可变==不可hash 2、不可变:值变,id就变。不可变==可hash)

二 数字

整型与浮点型

#整型int
  作用:年纪,等级,身份证号,qq号等整型数字相关
  定义:
    age=10 #本质age=int(10)

#浮点型float
  作用:薪资,身高,体重,体质参数等浮点数相关

    salary=3000.3 #本质salary=float(3000.3)

#二进制,十进制,八进制,十六进制

其他数字类型(了解)

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

#复数(了解,推荐视频:https://www.bilibili.com/video/av26786159)  
    >>> x=1-2j
    >>> x.real
    1.0
    >>> x.imag
    -2.0  

三 字符串

#作用:名字,性别,国籍,地址等描述信息

#定义:在单引号\双引号\三引号内,由一串字符组成
name='egon'

#优先掌握的操作:
#1、按索引取值(正向取+反向取) :只能取
#2、切片(顾头不顾尾,步长)
#3、长度len
#4、成员运算in和not in
#5、移除空白strip
#6、切分split
#7、循环

需要掌握的操作

#1、strip,lstrip,rstrip
#2、lower,upper
#3、startswith,endswith
#4、format的三种玩法
#5、split,rsplit
#6、join
#7、replace
#8、isdigit
# strip 默认移除空格
name = '*egon**'
print(name.strip('*'))    # 移除字符串两边的*     egon
print(name.lstrip('*'))   # 移除字符串左边的*     egon**
print(name.rstrip('*'))   # 移除字符串右边的*     *egon

# lower,upper 字母小写和大写
name = 'egon'
print(name.lower())  # 字符串字母小写 egon
print(name.upper())  # 字符串字母大写 EGON

# startswith,endswith   字符串判断是否以什么开头和结尾,返回结果布尔类型
name = 'alex_SB'
print(name.endswith('SB'))  # True
print(name.startswith('alex'))  # True

# format的三种玩法
res = '{} {} {}'.format('egon', 18, 'male')
res1 = '{1} {0} {1}'.format('egon', 18, 'male')
res2 = '{name} {age} {sex}'.format(sex='male', name='egon', age=18)
print(res)
print(res1)
print(res2)

# split     以什么为切片,返回结果列表
name = 'root:x:0:0::/root:/bin/bash'
print(name.split(':'))  # 默认分隔符为空格 ['root', 'x', '0', '0', '', '/root', '/bin/bash']
name = 'C:/a/b/c/d.txt'  # 只想拿到顶级目录
print(name.split('/', 1))  # ['C:', 'a/b/c/d.txt']
print(name.split('/', 2))  # ['C:', 'a', 'b/c/d.txt']
name = 'a|b|c'
print(name.rsplit('|', 1))  # 从右开始切分 ['a|b', 'c']

# join
tag = ' '
print(tag.join(['egon', 'say', 'hello', 'world']))  # 可迭代对象必须都是字符串 egon say hello world

# replace 替代
name = 'alex say :i have one tesla,my name is alex'
print(name.replace('alex', 'SB', 1))    # SB say :i have one tesla,my name is alex
print(name.replace('alex', 'SB', 3))    # SB say :i have one tesla,my name is SB


# isdigit:可以判断bytes和unicode类型,是最常用的用于于判断字符是否为"数字"的方法
age = input('>>: ')
print(age.isdigit())

其他操作(了解即可)

#1、find,rfind,index,rindex,count
#2、center,ljust,rjust,zfill
#3、expandtabs
#4、captalize,swapcase,title
#5、is数字系列
#6、is其他
# find,rfind,index,rindex,count
name = 'egon say hello'
print(name.find('o', 1, 3))  # 顾头不顾尾,找不到则返回-1不会报错,找到了则显示索引
# print(name.index('e',2,4)) #同上,但是找不到会报错
print(name.count('e', 1, 3))  # 顾头不顾尾,如果不指定范围则查找所有
# center,ljust,rjust,zfill
name = 'egon'
print(name.center(30, '-')) # -------------egon-------------
print(name.ljust(30, '*'))  # egon**************************
print(name.rjust(30, '*'))  # **************************egon
print(name.zfill(50))  # 用0填充   # 0000000000000000000000000000000000000000000000egon

# expandtabs
name = 'egon\thello'
print(name)  # egon    hello
print(name.expandtabs(1))  # egon hello

# captalize,swapcase,title
name = 'egon'
print(name.capitalize())  # 首字母大写 Egon
print(name.swapcase())  # 大小写翻转 EGON
msg = 'egon say hi'
print(msg.title())  # 每个单词的首字母大写 Egon Say Hi

# is数字系列
# 在python3中
num1 = b'4'  # bytes
num2 = u'4'  # unicode,python3中无需加u就是unicode
num3 = ''  # 中文数字
num4 = ''  # 罗马数字

# isdigt:bytes,unicode
print(num1.isdigit())  # True
print(num2.isdigit())  # True
print(num3.isdigit())  # False
print(num4.isdigit())  # False

# isdecimal:uncicode
# bytes类型无isdecimal方法
print(num2.isdecimal())  # True
print(num3.isdecimal())  # False
print(num4.isdecimal())  # False

# isnumberic:unicode,中文数字,罗马数字
# bytes类型无isnumberic方法
print(num2.isnumeric())  # True
print(num3.isnumeric())  # True
print(num4.isnumeric())  # True

# 三者不能判断浮点数
num5 = '4.3'
print(num5.isdigit())  # False
print(num5.isdecimal())  # False
print(num5.isnumeric())  # False
'''
总结:
    最常用的是isdigit,可以判断bytes和unicode类型,这也是最常见的数字应用场景
    如果要判断中文数字或罗马数字,则需要用到isnumeric
'''
# is其他
print('===>')
name = 'egon123'
print(name.isalnum())  # 字符串由字母或数字组成 True
print(name.isalpha())  # 字符串只由字母组成 False

print(name.isidentifier())  # True
print(name.islower())  # True
print(name.isupper())  # False
print(name.isspace())  # False
print(name.istitle())  # False

练习

name = " aleX"
# 1)    移除 name 变量对应的值两边的空格,并输出处理结果
print(name.strip())
# 2)    判断 name 变量对应的值是否以 "al" 开头,并输出结果print(name.startswith('al'))
# 3)    判断 name 变量对应的值是否以 "X" 结尾,并输出结果print(name.endswith('X'))
# 4)    将 name 变量对应的值中的 “l” 替换为 “p”,并输出结果
print(name.replace('l', 'p'))
# 5)    将 name 变量对应的值根据 “l” 分割,并输出结果。
print(name.split('l'))
# 6)    将 name 变量对应的值变大写,并输出结果print(name.upper())
# 7)    将 name 变量对应的值变小写,并输出结果print(name.lower())
# 8)    请输出 name 变量对应的值的第 2 个字符?
print(name[1])
# 9)    请输出 name 变量对应的值的前 3 个字符?
print(name[:3])
# 10)    请输出 name 变量对应的值的后 2 个字符?print(name[-2:])
# 11)    请输出 name 变量对应的值中 “e” 所在索引位置?print(name.find('e'))
# 12)    获取子序列,去掉最后一个字符。如: oldboy 则获取 oldbo。
a=name[:-1]
print(a)

四 列表

# 基本数据类型
# list
1、作用:按位置存放多个值
2、定义:在[]内,用逗号分隔开多个任意数据类型的值
# l1 = [1,'a',[1,2]] # 本质:l1 = list([1,'a',[1,2]])
3、类型转换
# 但凡能被for循环遍历的数据类型都可以传给list()转换成列表类型,list()会跟for循环一样遍历出数据类型中包含的每一个元素然后放到列表中
# >>> list('wdad') # 结果:['w', 'd', 'a', 'd']
# >>> list([1,2,3]) # 结果:[1, 2, 3]
# >>> list({"name":"jason","age":18}) #结果:['name', 'age']
# >>> list((1,2,3)) # 结果:[1, 2, 3]
# >>> list({1,2,3,4}) # 结果:[1, 2, 3, 4]
4、内置方法
# 1.按索引存取值(正向存取+反向存取):即可存也可以取  
# 1.1 正向取(从左往右)
>>> my_friends=['tony','jason','tom',4,5]
>>> my_friends[0]  
tony
# 1.2 反向取(负号表示从右往左)
>>> my_friends[-1]  
5
# 1.3 对于list来说,既可以按照索引取值,又可以按照索引修改指定位置的值,但如果索引不存在则报错
>>> my_friends = ['tony','jack','jason',4,5]
>>> my_friends[1] = 'martthow'
>>> my_friends
['tony', 'martthow', 'jason', 4, 5]

# 2.切片(顾头不顾尾,步长)
# 2.1 顾头不顾尾:取出索引为0到3的元素
>>> my_friends[0:4] 
['tony', 'jason', 'tom', 4]
# 2.2 步长:0:4:2,第三个参数2代表步长,会从0开始,每次累加一个2即可,所以会取出索引0、2的元素
>>> my_friends[0:4:2]  
['tony', 'tom']
# 2.3 my_friends[:] #切片等同于拷贝行为,而且相当于浅拷贝。
# 2.4 my_friends[::-1]  #整个列表取反,倒过来。

# 3.长度
>>> len(my_friends)
5

# 4.成员运算in和not in
>>> 'tony' in my_friends
True
>>> 'xxx' not in my_friends
True

# 5.添加
# 5.1 append()列表尾部追加元素
>>> l1 = ['a','b.txt','c']
>>> l1.append('d')
>>> l1
['a', 'b.txt', 'c', 'd']
# 5.2 extend()一次性在列表尾部添加多个元素(拼接作用)
>>> l1.extend(['a','b.txt','c'])
>>> l1
['a', 'b.txt', 'c', 'd', 'a', 'b.txt', 'c']
# 5.3 insert()在指定位置插入元素
>>> l1.insert(0,"first")  # 0表示按索引位置插值
>>> l1
['first', 'a', 'b.txt', 'c', 'alisa', 'a', 'b.txt', 'c']

# 6.删除
# 6.1 del :通用的删除方法,只是单纯的删除、没有返回值。
>>> l = [11,22,33,44]
>>> del l[2]  # 删除索引为2的元素,不支持赋值语法
>>> l
[11,22,44]
# 6.2 pop()默认删除列表最后一个元素,并将删除的值返回,括号内可以通过加索引值来指定删除元素
>>> l = [11,22,33,22,44]
>>> res=l.pop()
>>> res
44
>>> res=l.pop(1)
>>> res
22
# 6.3 remove()括号内指名道姓表示要删除哪个元素,返回None
>>> l = [11,22,33,22,44]
>>> res=l.remove(22) # 从左往右查找第一个括号内需要删除的元素
>>> print(res)
None

# 7.循环
# 循环遍历my_friends列表里面的值
for line in my_friends:
    print(line) 
'tony'
'jack'
'jason'
4

# 8.reverse()颠倒列表内元素顺序,不是排序,列表倒过来。
>>> l = [11,22,33,44]
>>> l.reverse()
>>> l
[44,33,22,11]

# 8.sort()给列表内所有元素排序
# 8.1 排序时列表元素之间必须是相同数据类型,不可混搭,否则报错
>>> l = [11,22,3,42,7,55]
>>> l.sort()
>>> l
[3, 7, 11, 22, 42, 55]  # 默认从小到大排序
>>> l = [11,22,3,42,7,55]
>>> l.sort(reverse=True)  # reverse用来指定是否跌倒排序,默认为False
>>> l
[55, 42, 22, 11, 7, 3]
# 8.2 了解知识:
# 我们常用的数字类型直接比较大小,但其实,字符串、列表等都可以比较大小,
  原理相同:都是依次比较对应位置的元素的大小,如果分出大小,则无需比较下一个元素,比如
>>> l1=[1,2,3]
>>> l2=[2,]
>>> l2 > l1
True
# 字符之间的大小取决于它们在ASCII表中的先后顺序,越往后越大
>>> s1='abc'
>>> s2='az'
>>> s2 > s1 # s1与s2的第一个字符没有分出胜负,但第二个字符'z'>'b.txt',所以s2>s1成立
True
了解:列表也可以比大小,原理同字符串一样,必须同种类型
# 所以我们也可以对下面这个列表排序
>>> l = ['A','z','adjk','hello','hea']
>>> l.sort()
>>> l
['A', 'adjk', 'hea', 'hello','z']

# 9、count index clear
# l = [1, 1, 22, 1, 24]
# # res1 = l.count(1)    # 1有几个  3 [1, 1, 22, 1, 24]
# # res2 = l.index(22)  # 找索引,找不到报错 2 [1, 1, 22, 1, 24]
# res3 = l.clear()  # 清除列表,返回一个None  None []
# # print(res1,l)
# # print(res2,l)
# print(res3,l)

# 补充
# 1、队列:FIFO,先进先出(商场自动扶梯,先站上去的人,先出去)
l=[]
# 入队操作
l.append('first')
l.append('second')
l.append('third')
print(l)
# 出队操作
print(l.pop(0))
print(l.pop(0))
print(l.pop(0))

# 2、堆栈:LIFO,后进后出(向衣柜里叠衣服,后叠进去的,先拿出来)
l = []
# 入栈操作
l.append('first')
l.append('second')
l.append('third')
print(l)
# 出栈操作
print(l.pop())
print(l.pop())
print(l.pop())
练习
# 1. 有列表data=['alex',49,[1900,3,18]],分别取出列表中的名字,年龄,出生的年,月,日赋值给不同的变量
data = ['alex', 49, [1900, 3, 18]]
name = data[0]
age = data[1]
year = data[2][0]
month = data[2][1]
day = data[2][2]
# 2. 用列表模拟队列
l = []
l.append('a')
l.append('b')
l.append('c')
l.pop(0)
l.pop(0)
l.pop(0)
# 3. 用列表模拟堆栈
l1 = []
l1.append('a')
l1.append('b')
l1.append('c')
l1.pop()
l1.pop()
l1.pop()
# 4. 有如下列表,请按照年龄排序(涉及到匿名函数)
l2 = [
    {'name': 'alex', 'age': 84},
    {'name': 'oldboy', 'age': 73},
    {'name': 'egon', 'age': 18},
]
l2.sort(key=lambda item: item['age'])
print(l2)

五 元组

1、元组与列表类似("一个不可变的列表”),也是可以存多个任意类型的元素,不同之处在于元组的元素不能修改。
# 即元组相当于不可变的列表,用于记录多个固定不允许修改的值,单纯用于取,只用于读不用于改
2、定义:
在()内用逗号分隔开多个任意类型的值
# >>> countries = ("中国","美国","英国") # 本质:countries = tuple("中国","美国","英国")
强调:如果元组内只有一个值,则必须加一个逗号,否则()就只是包含的意思而非定义元组
# >>> countries = ("中国",) # 本质:countries = tuple("中国")
强调,元组不能改,是指元组对应内存地址不能改,元组里含有列表等可变类型数据,在列表内的内容可以改变
3、类型转换
# 但凡能被for循环的遍历的数据类型都可以传给tuple()转换成元组类型
>>> tuple('wdad') # 结果:('w', 'd', 'a', 'd')
>>> tuple([1,2,3]) # 结果:(1, 2, 3)
>>> tuple({"name":"jason","age":18}) # 结果:('name', 'age')
>>> tuple((1,2,3)) # 结果:(1, 2, 3)
>>> tuple({1,2,3,4}) # 结果:(1, 2, 3, 4)
# tuple()会跟for循环一样遍历出数据类型中包含的每一个元素然后放到元组中
4、使用
>>> tuple1 = (1, 'hhaha', 15000.00, 11, 22, 33) 
4.1 按索引取值(正向取+反向取):只能取,不能改否则报错!  
>>> tuple1[0]
1
>>> tuple1[-2]
22
>>> tuple1[0] = 'hehe'  # 报错:TypeError:
4.2 切片(顾头不顾尾,步长)
>>> tuple1[0:6:2] 
(1, 15000.0, 22)
4.3 长度
>>> len(tuple1)  
6
4.4 成员运算 innot in
>>> 'hhaha' in tuple1 
True
>>> 'hhaha' not in tuple1  
False 
5、循环

>>> for line in tuple1:
...     print(line)
1
hhaha
15000.0
11
22
33
6、内置方法(两种)
t = (1, 2, 34, 5)
t1 = t.count(1)
t2 = t.index(34)
print(t1, type(t1))
print(t2, type(t2))

练习

# 简单购物车,要求如下:
# 实现打印商品详细信息,用户输入商品名和购买个数,则将商品名,价格,购买个数加入购物列表,如果输入为空或其他非法输入则要求用户重新输入  
msg_dic = {
    'apple': 10,
    'tesla': 100000,
    'mac': 3000,
    'lenovo': 30000,
    'chicken': 10,
}

l = []
while True:
    for key, item in msg_dic.items():
        print('商品名:{}, 价格:{}元!'.format(key, item))
    product_name = input('请输入商品名:').strip()
    if not product_name or product_name not in msg_dic:continue
    count = input('购买个数:').strip()
    if not count.isdigit():continue
    l.append((product_name, msg_dic[product_name], count))
    print(l)

六 字典

1、作用
2、定义:在{}内用逗号分隔开多元素,每一个元素都是key:value的形式,其中value可以是任意类型
# 而key则必须是不可变类型,key不重复,详见第八小节,通常key应该是str类型,因为str类型会对value有描述性的功能
info={'name':'tony','age':18,'sex':'male'} #本质info=dict({....})
# 也可以这么定义字典
info=dict(name='tony',age=18,sex='male') # info={'age': 18, 'sex': 'male', 'name': 'tony'}

d={}    #默认定义出来的是空字典
d1=dict()   #也定义空字典
print(d,d1)
3、数据类型转换
转换1:
info = [['name', 'tony'], ('age', 18), ['sex', 'male']] d = {} for item in info: d[item[0]] = item[1] print(d) # {'name': 'tony', 'age': 18, 'sex': 'male'} res = dict(info) print(res) # {'name': 'tony', 'age': 18, 'sex': 'male'} 转换2:fromkeys会从元组中取出每个值当做key,然后与None组成key:value放到字典中 >>> {}.fromkeys(('name','age','sex'),None) {'age': None, 'sex': None, 'name': None}
4、内置方法

# 1.1 取
>>> dic = {
...     'name': 'xxx',
...     'age': 18,
...     'hobbies': ['play game', 'basketball']
... }
>>> dic['name']
'xxx'
>>> dic['hobbies'][1]
'basketball'
# 1.2 对于赋值操作,如果key原先不存在于字典,则会新增key:value
>>> dic['gender'] = 'male'  #列表对没有的索引赋值,会报错;类似与列表的append,insert  
>>> dic
{'name': 'tony', 'age': 18, 'hobbies': ['play game', 'basketball'],'gender':'male'}
# 1.3 对于赋值操作,如果key原先存在于字典,则会修改对应value的值
>>> dic['name'] = 'tony'
>>> dic
{'name': 'tony', 'age': 18, 'hobbies': ['play game', 'basketball']}

# 2、长度len
>>> len(dic) 
3

# 3、成员运算in和not in
>>> 'name' in dic  # 判断某个值是否是字典的key
True

# 4、删除
# 4.1 通用删除
dic={'name':'tony','age':18,'sex':'male'}
del dic['name']
print(dic)
# 4.2
>>>  res=dic.pop('name')  # 通过指定字典的key来删除字典的键值对,返回删除key对应的那个Value。
>>> dic
{'age': 18, 'hobbies': ['play game', 'basketball']}
>>> res
'tony'
# 4.3 popitem删除:随机删除,返回元组(删除的Key,删除Value)
res = dic.popitem()
print(res)  # ('sex', 'male')

# 5、键keys(),值values(),键值对items()    --》在python3中得到的是老母鸡,跟range一样的道理,节约内存
>>> dic = {'age': 18, 'hobbies': ['play game', 'basketball'], 'name': 'xxx'}
# 获取字典所有的key
>>> dic.keys()  #python2中输出是--》['name', 'age', 'hobbies']
dict_keys(['name', 'age', 'hobbies'])
# 获取字典所有的value
>>> dic.values()
dict_values(['xxx', 18, ['play game', 'basketball']])
# 获取字典所有的键值对
>>> dic.items()
dict_items([('name', 'xxx'), ('age', 18), ('hobbies', ['play game', 'basketball'])])

需要掌握得
1.get()
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}   #根据key取值,容错性好
>>> dic.get('k1')
'jason'  # key存在,则获取key对应的value值
>>> res=dic.get('xxx') # key不存在,不会报错而是默认返回None
>>> print(res)
None
>>> res=dic.get('xxx',666) # key不存在时,可以设置默认返回的值
>>> print(res)
666

ps:字典取值建议使用get方法


# 2.update()
# 用新字典更新旧字典,有则修改,无则添加
>>> dic= {'k1':'jason','k2':'Tony','k3':'JY'}
>>> dic.update({'k1':'JN','k4':'xxx'})
>>> dic
{'k1': 'JN', 'k3': 'JY', 'k2': 'Tony', 'k4': 'xxx'}

# 3.setdefault()
# key不存在则新增键值对,并将新增的value返回
>>> dic={'k1':111,'k2':222}
>>> res=dic.setdefault('k3',333)
>>> res
333
>>> dic # 字典中新增了键值对
{'k1': 111, 'k3': 333, 'k2': 222}

# key存在则不做任何修改,并返回已存在key对应的value值
>>> dic={'k1':111,'k2':222}
>>> res=dic.setdefault('k1',666)
>>> res
111
>>> dic # 字典不变
{'k1': 111, 'k2': 222}

练习

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

# 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'
l3 = s.split(' ')
print(l3)
dic = {}
for i in l3:
    dic[i] = l3.count(i)  # 字典给键赋值,就是给字典增加键值对
print(dic)

 七 集合

1、作用
集合、list、tuple、dict一样都可以存放多个值,但是集合主要用于:去重、关系运算


2、定义

定义:在{}内用逗号分隔开多个元素,集合具备以下三个特点:
     1:每个元素必须是不可变类型
2:集合内没有重复的元素
3:集合内元素无序

s = {1,2,3,4} # 本质 s = set({1,2,3,4})

# 注意1:列表类型是索引对应值,字典是key对应值,均可以取得单个指定的值,
而集合类型既没有索引也没有key与值对应,所以无法取得单个的值,而且对于集合来说,主要用于去重与关系运算,
根本没有取出单个指定值这种需求。
# 注意2:{}既可以用于定义dict,也可以用于定义集合,但是字典内的元素必须是key:value的格式,
现在我们想定义一个空字典和空集合,该如何准确去定义两者?
d = {} # 默认是空字典
s = set() # 这才是定义空集合


3、类型转换
# 但凡能被for循环的遍历的数据类型(强调:遍历出的每一个值都必须为不可变类型)都可以传给set()转换成集合类型
# >>> s = set([1,2,3,4])
# >>> s1 = set((1,2,3,4))
# >>> s2 = set({'name':'jason',})
# >>> s3 = set('egon')
# >>> s,s1,s2,s3
{1, 2, 3, 4} {1, 2, 3, 4} {'name'} {'e', 'o', 'g', 'n'}

4、使用
关系运算(类似于数学集合运算)
我们定义两个集合friends与friends2来分别存放两个人的好友名字,然后以这两个集合为例讲解集合的关系运算
friends1 = {"zero", "kevin", "jason", "egon"} # 用户1的好友们
friends2 = {"Jy", "ricky", "jason", "egon"} # 用户2的好友们
1)合集/并集(|):求两个用户所有的好友(重复好友只留一个)
# print(friends1|friends2) #无序得
# print(friends1.union(friends2))
2)交集(&):求两个用户的共同好友
print(friends1&friends2)
print(friends1.intersection(friends2)) #等价
3)差集(-):
# print(friends1 - friends2) # 求用户1独有的好友
# print(friends1.difference(friends2))
# print(friends2 - friends1) # 求用户2独有的好友
# print(friends2.difference(friends1))
4)对称差集(^) # 求两个用户独有的好友们(即去掉共有的好友)
print(friends1 ^ friends2)
5)值是否相等(==)
# >>> friends1 == friends2
# False

6)父集:一个集合是否包含另外一个集合
6.1 包含则返回True
>>> {1,2,3} > {1,2}
True
print({1,2,3}.issuperset({1,2})
print({1,2}.issubset({1,2,3})
>>> {1,2,3} >= {1,2}
True
6.2 不存在包含关系,则返回False
>>> {1,2,3} > {1,3,4,5}
False
>>> {1,2,3} >= {1,3,4,5}
False

 7)子集
>>> {1,2} < {1,2,3}
True
>>> {1,2} <= {1,2,3}
True
8)长度
>>> s={'a','b.txt','c'}
>>> len(s)
3

9)成员运算
>>> 'c' in s
True

10)循环
>>> for item in s:
... print(item)
...
c
a
b.txt

5 去重(局限性)
# 1. 只能针对不可变类型
# 2. 集合本身是无序的,去重之后无法保留原来的顺序
>>> l=['a','b.txt',1,'a','a']
>>> s=set(l)
>>> s # 将列表转成了集合
{'b.txt', 'a', 1}
>>> l_new=list(s) # 再将集合转回列表
>>> l_new
['b.txt', 'a', 1] # 去除了重复,但是打乱了顺序

# 针对不可变类型,并且保证顺序则需要我们自己写代码实现,例如
l=[
{'name':'lili','age':18,'sex':'male'},
{'name':'jack','age':73,'sex':'male'},
{'name':'tom','age':20,'sex':'female'},
{'name':'lili','age':18,'sex':'male'},
{'name':'lili','age':18,'sex':'male'},
]

new_l=[]

for dic in l:
if dic not in new_l:
new_l.append(dic)

print(new_l)
# 结果:既去除了重复,又保证了顺序,而且是针对不可变类型的去重
[
{'age': 18, 'sex': 'male', 'name': 'lili'},
{'age': 73, 'sex': 'male', 'name': 'jack'},
{'age': 20, 'sex': 'female', 'name': 'tom'}
]

6 其他内置方法
# s={1,2,3}
1)discard
# s.discard(4) #删除元素不存在do nothing
# print(s)
# s.remove(4) #删除元素不存在则报错

2)update
# s.update({1,3,5})
# print(s)

3)pop
# res=s.pop()
# print(res)
# print(s)

4)add
# s.add(4)
# print(s)
练习
一.关系运算
  有如下两个集合,pythons是报名python课程的学员名字集合,linuxs是报名linux课程的学员名字集合
  pythons={'alex','egon','yuanhao','wupeiqi','gangdan','biubiu'}
  linuxs={'wupeiqi','oldboy','gangdan'}
  1. 求出即报名python又报名linux课程的学员名字集合
  2. 求出所有报名的学生名字集合
  3. 求出只报名python课程的学员名字
  4. 求出没有同时这两门课程的学员名字集合

# 有如下两个集合,pythons是报名python课程的学员名字集合,linuxs是报名linux课程的学员名字集合
pythons={'alex','egon','yuanhao','wupeiqi','gangdan','biubiu'}
linuxs={'wupeiqi','oldboy','gangdan'}
# 求出即报名python又报名linux课程的学员名字集合
print(pythons & linuxs)
# 求出所有报名的学生名字集合
print(pythons | linuxs)
# 求出只报名python课程的学员名字
print(pythons - linuxs)
# 求出没有同时这两门课程的学员名字集合
print(pythons ^ linuxs)
二.去重

   1. 有列表l=['a','b',1,'a','a'],列表元素均为可hash类型,去重,得到新列表,且新列表无需保持列表原来的顺序

   2.在上题的基础上,保存列表原来的顺序

   3.去除文件中重复的行,肯定要保持文件内容的顺序不变
   4.有如下列表,列表元素为不可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=['a','b',1,'a','a']
print(set(l))

#去重,并保持原来的顺序
#方法一:不用集合
l=[1,'a','b',1,'a']

l1=[]
for i in l:
    if i not in l1:
        l1.append(i)
print(l1)
#方法二:借助集合 l1=[] s=set() for i in l: if i not in s: s.add(i) l1.append(i) print(l1) # 同上方法二,去除文件中重复的行 import os with open('db.txt','r',encoding='utf-8') as read_f,\ open('.db.txt.swap','w',encoding='utf-8') as write_f: s=set() for line in read_f: if line not in s: s.add(line) write_f.write(line) os.remove('db.txt') os.rename('.db.txt.swap','db.txt') # 列表中元素为可变类型时,去重,并且保持原来顺序 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'}, ] # print(set(l)) #报错:unhashable type: 'dict' s=set() l1=[] for item in l: val=(item['name'],item['age'],item['sex']) if val not in s: s.add(val) l1.append(item) print(l1) # 定义函数,既可以针对可以hash类型又可以针对不可hash类型 def func(items,key=None): s=set() for item in items: val=item if key is None else key(item) if val not in s: s.add(val) yield item print(list(func(l,key=lambda dic:(dic['name'],dic['age'],dic['sex']))))

八 数据类型总结

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

数字
字符串
集合:无序,即无序存索引相关信息
元组:有序,需要存索引相关信息,不可变
列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
字典:无序,需要存key与value映射的相关信息,可变,需要处理数据的增删改
按存值个数区分
标量/原子类型 数字,字符串
容器类型 列表,元组,字典
 
 按可变不可变区分
可变 列表,字典
不可变 数字,字符串,元组
按访问顺序区分
直接访问 数字
顺序访问(序列类型) 字符串,列表,元组
key值访问(映射类型) 字典
 
 

 

九、 作业

#作业一: 三级菜单
#要求:
打印省、市、县三级菜单
可返回上一级
可随时退出程序
menu = {
    '北京':{
        '海淀':{
            '五道口':{
                'soho':{},
                '网易':{},
                'google':{}
            },
            '中关村':{
                '爱奇艺':{},
                '汽车之家':{},
                'youku':{},
            },
            '上地':{
                '百度':{},
            },
        },
        '昌平':{
            '沙河':{
                '老男孩':{},
                '北航':{},
            },
            '天通苑':{},
            '回龙观':{},
        },
        '朝阳':{},
        '东城':{},
    },
    '上海':{
        '闵行':{
            "人民广场":{
                '炸鸡店':{}
            }
        },
        '闸北':{
            '火车战':{
                '携程':{}
            }
        },
        '浦东':{},
    },
    '山东':{},
}


# 方法一
tag=True
while tag:
    menu1=menu
    for key in menu1: # 打印第一层
        print(key)

    choice1=input('第一层>>: ').strip() # 选择第一层

    if choice1 == 'b': # 输入b,则返回上一级
        break
    if choice1 == 'q': # 输入q,则退出整体
        tag=False
        continue
    if choice1 not in menu1: # 输入内容不在menu1内,则继续输入
        continue

    while tag:
        menu_2=menu1[choice1] # 拿到choice1对应的一层字典
        for key in menu_2:
            print(key)

        choice2 = input('第二层>>: ').strip()

        if choice2 == 'b':
            break
        if choice2 == 'q':
            tag = False
            continue
        if choice2 not in menu_2:
            continue

        while tag:
            menu_3=menu_2[choice2]
            for key in menu_3:
                print(key)

            choice3 = input('第三层>>: ').strip()
            if choice3 == 'b':
                break
            if choice3 == 'q':
                tag = False
                continue
            if choice3 not in menu_3:
                continue

            while tag:
                menu_4=menu_3[choice3]
                for key in menu_4:
                    print(key)

                choice4 = input('第四层>>: ').strip()
                if choice4 == 'b':
                    break
                if choice4 == 'q':
                    tag = False
                    continue
                if choice4 not in menu_4:
                    continue

                # 第四层内没数据了,无需进入下一层

# 方法二
#part1(初步实现):能够一层一层进入
layers = [menu, ]

while True:
    current_layer = layers[-1]
    for key in current_layer:
        print(key)

    choice = input('>>: ').strip()

    if choice not in current_layer: continue

    layers.append(current_layer[choice])



#part2(改进):加上退出机制
layers=[menu,]

while True:
    if len(layers) == 0: break
    current_layer=layers[-1]
    for key in current_layer:
        print(key)

    choice=input('>>: ').strip()

    if choice == 'b':
        layers.pop(-1)
        continue
    if choice == 'q':break

    if choice not in current_layer:continue

    layers.append(current_layer[choice])

 




 

posted @ 2023-03-19 19:38  coder雪山  阅读(24)  评论(0编辑  收藏  举报