一、数据类型
1 什么是数据?
name='sunkedong'#字符串类型 age=24 #整型 date=2017.9#浮点型 dic={'name':'sunkedong','age':16}#字典类型 list=['sunkedong','18','24','man'] #列表类型 #以上都表示存储的数据
2 为何数据要分不同的类型
数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示
3 数据类型
数字(整形,长整形,浮点型,复数)
字符串
字节串:在介绍字符编码时介绍字节bytes类型
列表
元组
字典
集合
4 按照以下几个点展开数据类型的学习
#一:基本使用 1 用途 2 定义方式 3 常用操作+内置的方法 #二:该类型总结 1 存一个值or存多个值 只能存一个值 可以存多个值,值都可以是什么类型 2 有序or无序 3 可变or不可变 !!!可变:值变,id不变。可变==不可hash !!!不可变:值变,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'> #复数(了解) >>> x=1-2j >>> x.real 1.0 >>> x.imag -2.0
在定义变量时,如果字符串或整数的话 在短字符的情况下 两个变量id 相同,如果长字符或整数,id不同
三、字符串操作
#作用:名字,性别,国籍,地址等描述信息 #定义:在单引号\双引号\三引号内,由一串字符组成 name='egon' #优先掌握的操作: 按索引取值(正向取+反向取) :只能取 切片(顾头不顾尾,步长) 长度len 成员运算in和not in 移除空白strip 切分split 循环
3.2、strip移除空白或自定义字符(常用)
#默认会把空格取掉 name = 'sunkedong ' print(name.strip()) #这样可以指定*号 去掉 name='*sunkedong**' print(name.strip('*')) #去掉左边的* print(name.lstrip('*')) #去掉右边的* print(name.rstrip('*')) #注意:不能去掉中间的内容
3.3、匹配开头和结尾(常用)
name='sunkedong_dz' #如果结尾_dz 为真
print(name.endswith('dz'))
#如果开头为sun 为真 print(name.startswith('sun'))
3.4、替换(常用)
name='My name is sunkedong,I love sunkedong' #默认为-1 全部替换 print(name.replace('sunkedong','sunkd',-1)) #1 代表替换一次 print(name.replace('sunkedong','sunkd',1))
3.5、切片(常用)
user_info='root:x:/root:/bin/bash' # 取第一个和第三个,因为顾头不顾尾 print(user_info[0:4]) #以冒号分割 print(user_info.split(':')[0]) #以冒号分割 取第一次的结果 print(user_info.split(':',1))
备注:切成列表展示
3.6、format(常用)
msg='My name is {},age is {},sex is{}'.format('sunkedong',24,'man') print(msg) msg1='My name is {0},age is {1},sex is {2}'.format('sunkedong',24,'man') print(msg1) #这种方式最常用 msg2='My name is {name},age is {age},sex is {sex}'.format(name='sunkedong',sex='man',age=24) print(msg2)
3.7、字符串的查找(常用)
#find,rfind,index,rindex,count
jobs='My job is carry the engineers' print(jobs.find('job',1,6))#顾头不顾尾,找不到则返回-1 ,找到了现实索引, print(jobs.index('t',0,22))#同上,但是找不到会报错 print(jobs.count('e',1,25))#顾头不顾尾,如果不指定范围,则查找所有,查找指定字符串的和
find 查找不到报-1(常用方式) index 查找报错 都不常用,后面会用到正则表达式
3.8、split 字符串的切分(常用)
msg='root:x:0:0:root:/root:/bin/bash' print(msg.split(':')) #指定:号来分割,默认是空格 name='C:/a/b/c/d.txt' print(name.split('/',1)) #切割1次 name1='root|mayi|admin' print(name1.rsplit('|',1)) #从右边切一次
3.9、join(常用)
tag=' ' print(tag.join(['sunkedong','sunkezhou','wuguoju'])) # 连接字符串数组 以空格连接
3.10、字符填充(常用)
#center,ljust,rjust,zfill name='sunkedong' print(name.center(30,'-')) #全局填充为30个字符,填充物为- print(name.ljust(30,'*'))#左边填充* 到30个字符 print(name.rjust(30,'*'))#右边填充* 到30个字符 print(name.zfill(30))#填充0 到30个字符
3.11、 转换为空格
name='sunke\tdong' print(name) print(name.expandtabs(2)) #把tab键转换为2个空格
3.12、大小写转换
name='sunkedong' print(name.lower()) #大写转换为小写 # print(name.swapcase()) print(name.upper())# 小写转换为大写 #captalize,swapcase,title print(name.capitalize()) #首字母大写 print(name.swapcase()) #大小写翻转 msg='egon say hi' print(msg.title()) #每个单词的首字母大写
3.13、数字的判断(isdigit最常用)
#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()) print(num5.isdecimal()) print(num5.isnumeric()) 总结: 最常用的是isdigit,可以判断bytes和unicode类型,这也是最常见的数字应用场景 如果要判断中文数字或罗马数字,则需要用到isnumeric
3.14、is的其他用法
#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())
字符串相关的练习总结
# 写代码,有如下变量,请按照要求实现每个功能 (共6分,每小题各0.5分) name = " aleX" # 1) 移除 name 变量对应的值两边的空格,并输出处理结果 # 2) 判断 name 变量对应的值是否以 "al" 开头,并输出结果 # 3) 判断 name 变量对应的值是否以 "X" 结尾,并输出结果 # 4) 将 name 变量对应的值中的 “l” 替换为 “p”,并输出结果 # 5) 将 name 变量对应的值根据 “l” 分割,并输出结果。 # 6) 将 name 变量对应的值变大写,并输出结果 # 7) 将 name 变量对应的值变小写,并输出结果 # 8) 请输出 name 变量对应的值的第 2 个字符? # 9) 请输出 name 变量对应的值的前 3 个字符? # 10) 请输出 name 变量对应的值的后 2 个字符? # 11) 请输出 name 变量对应的值中 “e” 所在索引位置? # 12) 获取子序列,去掉最后一个字符。如: oldboy 则获取 oldbo。
四、列表
列表操作
列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储、修改等操作
重点(有限掌握)
定义列表
msg=['sunkdong',18,'man','IT','henan','beijing']
取值
print(msg[2])#正取 print(msg[-1])#反向取 print(id(msg))#查看id
切片
print(msg[0:3])#取索引0,1,2,的值,顾头不顾尾 print(msg[0:5:3]) #取索引0,1,2,3,4 步长为3,步长的意思应该就是隔2(笨方法)
长度
print(len(msg))#显示元素个数
成员运算
print('sunkd' in msg) print('sunkedong' in msg) print(18 in msg)
列表的删除
msg.append('test') # print(msg) del msg[6]#利用内置方法删除,不推荐使用 print(msg) msg.pop() #安照索引删除,默认从末尾开始删除。而且会保存被删除 的值 rs=msg.pop()#查看保存的值 print(rs) print(msg)
追加
msg.append('test') print(msg)
删除
msg.append('test') # print(msg) del msg[6]#利用内置方法删除,不推荐使用 print(msg) msg.pop() #安照索引删除,默认从末尾开始删除。而且会保存被删除 的值 rs=msg.pop()#查看保存的值 print(rs) print(msg)
常用操作 插入内容
msg=['sunkdong',18,'man','IT','henan','beijing'] msg.insert(0,'test2')#在0元素后面插入 msg.insert(2,'test1')#在2元素后面插入 print(msg) msg.extend([1,2,3,4])#末尾追加多个元素 print(msg)
了解即可
msg.clear()#清除列表内容 print(msg) c=msg.copy() #复制列表到另一个列表 print(msg) print(c)
my_girl_friends.reverse()#列表的反转 print(my_girl_friends) l=[3,4,-1,2] l.sort(reverse=True) print(l)
练习
#队列:先进先出 #append,pop l1=[] l1.append('first') l1.append('second') l1.append('third') print(l1.pop(0)) print(l1.pop(0)) print(l1.pop(0)) #堆栈:先进后出 l1=[] l1.append('first') l1.append('second') l1.append('third') print(l1.pop()) print(l1.pop()) print(l1.pop()) l1=[] l1.insert(0,'first') l1.insert(0,'second') l1.insert(0,'third') print(l1) print(l1.pop(0)) print(l1.pop(0)) print(l1.pop(0))
元组
作用:存多个值,对比列表来说,元组不可变(是可以当做字典的key的),主要是用来读
定义方式:
ages=(10,12,18,33,18) #ages=tuple((10,12,18,33)) print(id(ages),type(ages),ages)
优先掌握的知识点:
#按照索引取值,正向和反向取值 print(ages[3]) print(ages[-1]) print(ages[0:2])#切片,顾头不顾尾 print(10 in ages)#判断值是否在列表中 print(len(ages))#取出值的长度 #其他操作 print(ages.index(32)) #查找对应的索引位置 print(ages.count(22))#查找值有多少个
练习循环取值
while循环的方式
l=['a','b','c','d','e'] ll='a,b,c,d,e' lll=('a','b','c','d','e') index=0 while index < len(l): print(l[index]) index+=1 while index < len(ll): print(ll[index].strip(',')) index+=1 while index < len(lll): print(lll[index]) index+=1
for循环的方式读取列表
for key in l: print(key) for key in ll: print(key) for key in lll: print(key)
#也可以循环序列 for i in range(1,10): print(i)
#下面这种方式相当于先取出元素个数,然后在根据个数来循环索引所对应的值
for i in range(len(l)):
print(i,l[i])
结论:for循环 对于这种循环方式比较高效,无序类型不适合用循环读取
字典类型
作用:存多个值,key-value存取,取值速度快
定义:key必须是不可变类型,value可以是任意类型
msg={'name':'sunkedong','age':24,'sex':'man','jobs':'IT'} msg1={'name':'mayun','msg':['sleep','play']}#字典里面可以套用列表 # msg2={[1,2,3]:num}#列表不能当字典的key print(msg['name'])
#取出长度
print(len(msg))
#成员运算 if 'name' in msg: print('ok')
if 'sunkz' not in msg:
msg['sunkdz']=('music')
else:
msg['sunkz']=('read')
删除
print(info.pop('name'))
print(info.pop('name1213','确实是没有的,我的哥'))
print(info.pop('name1213',None))
print(msg.keys())#打印键 print(msg.values())#打印值 print(msg.items())#打印键值对 for key in msg.keys():#循环取出键 print(key) for valaues in msg.values():#循环取出值 print(valaues) for item in msg.items(): #循环取出键值对 print(item[0],item[1])
for k,v in msg.items():# print(k,v)
常用方法
print(msg['name123'])#如果没有会报错 print(msg.get('name123'))#如果没有不会报错,返回none print(msg.popitem())#删除最后一对键值对
print(msg.setdefault('name1',['read','muscic'])) #有则不改,返回已经有的值,没有则新增,返回新增的值 print(msg)
查找 如果不在给个默认值
print(id(msg.setdefault('def',['123','234']))) print(msg) print(id(msg['def']))
了解
info_new={'a':1,'age':19} info.update(info_new) print(info) dic={'name':None,'age':None,'sex':None,'hobbies':None} dic1={}.fromkeys(['name','age','hobbies'],None) print(dic1)
集合
关系运算
作用:去重,关系运算,
# 定义:
# 1:每个元素必须是不可变类型(可hash,可作为字典的key)
# 2:没有重复的元素
# 3:无序
s={1,2,'a','b','c','d','e','f'} #s=set({1,2,'a'}) print(type(s),s)
# 优先掌握的操作:
# 长度len
s={1,2,'a','b','c','d','e','f'} print(len(s)) # 成员运算in和not in print('a' in s) for item in s: print(item)
# | 并集
s1={1,2,3} s2={3,4,5} print(s1 | s2)
# & 交集
print(s1 & s2)
# -差集
print(s1 - s2) print(s2 - s1)
# ^ 对称差集
s1={1,2,3}
s2={3,4,5}
==
> , >= , <, <= 父集,子集
s1={1,2,3,4} s2={3,4,5} print(len(s1) > len(s2)) s1={1,2,3,4} s2={3,4} print(s1 > s2) print(s1 >= s2)
print(s1.issuperset(s2))
print(s2.issubset(s1))
#去重 # l=['a','b',1,'a','a'] # print(list(set(l))) # l=['a','b',1,'a','a'] # l_new=list() # s=set() # for item in l: # if item not in s: # s.add(item) # l_new.append(item) 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_new=list() s=set() for item in l: res = (item['name'], item['age'], item['sex']) if res not in s: s.add(res) l_new.append(item) print(l_new) #了解:不可变集合 fset=frozenset({1,2,3}) fset.
练习
有如下两个集合,pythons是报名python课程的学员名字集合,linuxs是报名linux课程的学员名字集合
pythons={'alex','egon','yuanhao','wupeiqi','gangdan','biubiu'}
linuxs={'wupeiqi','oldboy','gangdan'}
1. 求出即报名python又报名linux课程的学员名字集合
2. 求出所有报名的学生名字集合
3. 求出只报名python课程的学员名字
4. 求出没有同时这两门课程的学员名字集合
pythons={'alex','egon','yuanhao','wupeiqi','gangdan','biubiu'} linuxs={'wupeiqi','oldboy','gangdan'} print(pythons&linuxs) print(pythons|linuxs) print(pythons) print(pythons^linuxs)
bool类型
bool值:所有的数据类型都自带布尔值
#布尔值为假的情况:0,空,None
x=None
# print(bool(x))
if x:
print('ok')
else:
print('ono')
字符编码
1. 计算机基础知识
2. 文本编辑器存取文件的原理(nodepad++,pycharm,word)
打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放与内存中的,断电后数据丢失
要想永久保存,需要点击保存按钮:编辑器把内存的数据刷到了硬盘上。
在我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。
3. python解释器执行py文件的原理 ,例如python test.py
第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器
第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中(小复习:pyhon的解释性,决定了解释器只关心文件内容,不关心文件后缀名)
第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码( ps:在该阶段,即执行时,才会识别python的语法,执行文件内代码,执行到name="egon",会开辟内存空间存放字符串"egon")
总结python解释器与文件本编辑的异同:
相同点:python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样
不同点:文本编辑器将文件内容读入内存后,是为了显示or编辑,根本不去理会python的语法,而python解释器将文件内容读入内存后,是为了执行,会识别python语法。
二、 什么是字符编码
计算机要想工作必须通电,即用‘电’驱使计算机干活,也就是说‘电’的特性决定了计算机的特性。电的特性即高低电平(人类从逻辑上将二进制数1对应高电平,二进制数0对应低电平),关于磁盘的磁特性也是同样的道理。结论:计算机只认识数字
很明显,我们平时在使用计算机时,用的都是人类能读懂的字符(用高级语言编程的结果也无非是在文件内写了一堆字符),如何能让计算机读懂人类的字符?
必须经过一个过程:
字符--------(翻译过程)------->数字
这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码
以下两个场景下涉及到字符编码的问题:
1. 一个python文件中的内容是由一堆字符组成的,存取均涉及到字符编码问题(python文件并未执行,前两个阶段均属于该范畴)
2. python中的数据类型字符串是由一串字符组成的(python文件执行时,即第三个阶段)
三 字符编码的发展史
阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符
ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符)
后来为了将拉丁文也编码进了ASCII表,将最高位也占用了
阶段二:为了满足中文,中国人定制了GBK
GBK:2Bytes代表一个中文字符,1Bytes表示一个英文字符
为了满足其他国家,各个国家纷纷定制了自己的编码
日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里
阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
于是产生了unicode(定长), 统一用2Bytes代表一个字符, 虽然2**16-1=65535,但unicode却可以存放100w+个字符,因为unicode存放了与其他编码的映射关系,准确地说unicode并不是一种严格意义上的字符串编码表,下载pdf来查看unicode的详情:
链接:https://pan.baidu.com/s/1dEV3RYp
很明显对于通篇都是英文的文本来说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)
于是产生了UTF-8(可变长),对英文字符只用1Bytes表示,对中文字符用3Bytes,对其他生僻字用更多的字节Bytes去存
需要强调的是:
毫无疑问utf-8比unicode更节省空间,而且都能兼容万国,那为何不全部采用utf-8呢?
其一:如果我们能统一全世界,废除所有现有的计算机编码体系,然后大一统都采用utf-8,那么乱码问题将不复存在,很明显很多地方仍会采用各种各样的编码,这是历史遗留问题。因而我们必须寻求一种与全世界的编码都有映射关系的解决方案,这就是unicode,而utf8是没有与其他编码的映射关系的。
其二:内存中统一采用unicode,浪费空间来换取可以转换成任意编码(不乱码),硬盘可以采用各种编码,如utf-8,保证存放于硬盘或者基于网络传输的数据量很小,提高传输效率与稳定性。
四.字符编码分类(简单了解)
计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号
当然我们编程语言都用英文没问题,ASCII够用,但是在处理数据时,不同的国家有不同的语言,日本人会在自己的程序中加入日文,中国人会加入中文。
而要表示中文,单拿一个字节表表示一个汉子,是不可能表达完的(连小学生都认识两千多个汉字),解决方法只有一个,就是一个字节用>8位2进制代表,位数越多,代表的变化就多,这样,就可以尽可能多的表达出不通的汉字
所以中国人规定了自己的标准gb2312编码,规定了包含中文在内的字符->数字的对应关系。
日本人规定了自己的Shift_JIS编码
韩国人规定了自己的Euc-kr编码(另外,韩国人说,计算机是他们发明的,要求世界统一用韩国编码)
这时候问题出现了,精通18国语言的小周同学谦虚的用8国语言写了一篇文档,那么这篇文档,按照哪国的标准,都会出现乱码(因为此刻的各种标准都只是规定了自己国家的文字在内的字符跟数字的对应关系,如果单纯采用一种国家的编码格式,那么其余国家语言的文字在解析时就会出现乱码)
所以迫切需要一个世界的标准(能包含全世界的语言)于是unicode应运而生(韩国人表示不服,然后没有什么卵用)
ascii用1个字节(8位二进制)代表一个字符
unicode常用2个字节(16位二进制)代表一个字符,生僻字需要用4个字节
例:
字母x,用ascii表示是十进制的120,二进制0111 1000
汉字中
已经超出了ASCII编码的范围,用Unicode编码是十进制的20013
,二进制的01001110 00101101
。
字母x,用unicode表示二进制0000 0000 0111 1000,所以unicode兼容ascii,也兼容万国,是世界的标准
这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效
本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8
编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:
字符 | ASCII | Unicode | UTF-8 |
---|---|---|---|
A | 01000001 | 00000000 01000001 | 01000001 |
中 | x | 01001110 00101101 | 11100100 10111000 10101101 |
从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
五 字符编码的使用
unicode----->encode-------->utf-8
utf-8-------->decode---------->unicode
补充:
浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器
如果服务端encode的编码格式是utf-8, 客户端内存中收到的也是utf-8编码的结果。
5.1.2 文本编辑器nodpad++
详细看下面文章
http://www.cnblogs.com/linhaifeng/articles/5950339.html
作业1:
menu_dic={ '北京':{'昌平':{'十三陵':{},'莽山':{}},'海淀':{'香山':{},'凤凰岭':{}}}, '上海':{'浦东':{'新区':{},'迪士尼':{}},'宝山':{'码头':{},'公园':{}}}, '江苏':{'苏州':{'苏州园林':{},'古迹':{}},'绍兴':{'绍兴古城':{},'西施故里':{}}}, } tag = True select_list = menu_dic layers_list = [menu_dic] count=0 while tag: for select in select_list: print(select) select_city = input("输入你要去的城市[输入quit程序/exit退出上层菜单]:").strip() if select_city == "exit": print('退出程序') break if select_city== "quit": if count == 0: print('退出程序...') #第一次退出,count为0 break select_list = layers_list[-1] layers_list.pop() count-=1 elif select_city not in select_list:#如果输入不在列表中,退出本次循环 continue else: # print(layers_list) layers_list.append(select_list) #这里主要是quit使用 # print(layers_list) # print(select_list) select_list = select_list[select_city] # print(select_list) count+=1 #count+1
作业2:
shop_list = { 'apple': '8488', 'huawei': '3499', 'oppo': '2599' } user=open('user.txt'.encode('utf-8')) user_file=user.readline() user_line=user_file.split(':')[0] passwd=user_file.split(':')[1] count = 0 while count < 3: username = input('请输入用户名:').strip() password = input('请输入密码:').strip() if username == user_line and password == passwd: print('登录成功') gongzi = input('输入你的工资:') if gongzi.isdigit(): gongzi=int(gongzi) else: print('输入错误,请重试.') tag = True while tag: for k, v in shop_list.items(): print('商品信息:%s,价格:%s' % (k, v)) print('你的工资是%s' % (gongzi)) shop = input('需要买哪款?'.strip()) shop_num = input('需要买的数量?') if shop_num.isdigit(): shop_num=int(shop_num) else: print('请输入整数') continue if shop in shop_list: shop_price = int(shop_list[shop]) shop_all = (shop_price * shop_num) if shop_all > gongzi: print('余额不足!还想买%s,好好努力吧!少年' % (shop)) q = input('是否退出[y/n]') if q == 'y': break else: gongzi_sy = gongzi - shop_all print('已经添加到购物列表.') gongzi = gongzi_sy if 'gm' not in locals().keys(): gm = [shop] else: gm.append(shop) q = input('是否退出[y/n]') if q == 'y': for key in gm: print('您够买的商品如下:%s'%(key)) # print(gm) break else: count += 1 print('你已经输入%s次' % (count))