多级菜单
- 多级菜单
- 可依次选择进入各子菜单
- 所需新知识点:列表、字典
#!/usr/bin/env python # -*- coding: utf-8 -*- menu = { '北京':{ '海淀':{ '五道口':{ 'soho':{}, '网易':{}, 'google':{} }, '中关村':{ '爱奇艺':{}, '汽车之家':{}, 'youku':{}, }, '上地':{ '百度':{}, }, }, '昌平':{ '沙河':{ '老男孩':{}, '北航':{}, }, '天通苑':{}, '回龙观':{}, }, '朝阳':{}, '东城':{}, }, '上海':{ '闵行':{ "人民广场":{ '炸鸡店':{} } }, '闸北':{ '火车战':{ '携程':{} } }, '浦东':{}, }, '山东':{}, } current_level = menu last_level = [] while True: for key in current_level: print(key) choice = input(">>:").strip() if len(choice) ==0:break if choice =='b': if len(last_level)==0:break current_level = last_level[-1] last_level.pop() if choice not in current_level:continue last_level.append(current_level) current_level = current_level[choice]
字典
注意:当我们想循环删除字典里的value时,用下面的方法
dic = {'k1':'v1','k2':'v2','k3':'v3'} for k in list(dic.keys()): if 'k1' in k: del dic[k] print(dic)
以上代码运行结果:
{'k3': 'v3', 'k2': 'v2'}
查询
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} print(dic['name']) print(dic.get('namedf'))#用get,如果没有这个值,查询不会报错
以上代码运行结果
alex
None
add
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic['gender']='female' print(dic)#打印字典是无序的
以上代码运行结果
{'age': 18, 'gender': 'female', 'name': 'alex'}
change
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic['name']='lhf' print(dic)
以上代码运行结果
{'name': 'lhf', 'age': 18}
del
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} del dic['name'] print(dic)
以上代码运行结果
{'age': 18}
字典里嵌入其它数据类型
dic1={ 1:'alex', 'name':'lhf', (1,2,3):{'age':18}, 'name':'alex' } print(dic1[1]) print(dic1['name']) print(dic1[(1,2,3)]) print(dic1[(1,2,3)]['age'])
以上代码运行结果
alex alex {'age': 18} 18
字典的其它用法
dic1=dict.fromkeys('abc',1) print(dic1)
以上代码运行结果(注意:此处类似浅拷贝)
{'b': 1, 'c': 1, 'a': 1}
dict.fromkeys(seq[, value]))
dict.get(key, default=None)
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic2 =dict.fromkeys(['a','b'],1) print(dic2) print(dic.get('name'))
以上代码运行结果
{'b': 1, 'a': 1} alex
dict.items()
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} for k,v in dic.items(): print(k,v) print(dic.keys()) for i in dic.keys(): print('key is %s,value is %s'%(i,dic[i]))
以上代码运行结果
age 18 name alex dict_keys(['age', 'name']) key is age,value is 18 key is name,value is alex
指定删除
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic.pop('name') print(dic)
以上代码运行结果
{'age': 18}
随机删除
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic.popitem() print(dic)
以上代码运行结果
{'name': 'alex'}
dict.setdefault(key, default=None)
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic.setdefault('gender',[]).append('male') dic['gender'].append('female')
以上代码运行结果
{'age': 18, 'name': 'alex', 'gender': ['male', 'female']}
dict.update(dict2)
__author__ = "zhou" #!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} dic1 = {'gender':'male','name':'ldf'} dic.update(dic1) print(dic)
以上代码运行结果
{'name': 'ldf', 'age': 18, 'gender': 'male'}
常用的取字典里面键值的方法
#!/usr/bin/env python # -*- coding: utf-8 -*- dic={'name':'alex','age':18} for k in dic: print(k,dic[k]) for i in dic.values(): print(i)
以上代码运行结果
age 18 name alex 18 alex
深浅拷贝
不同数据类型在内存中的存址方式:
字符串,数字,在内存中一次性创建,不能被修改,只要修改,就再创建。
列表,在内存中以类似链表,记录上一个元素的位置,以及下一个元素的位置,不连续的方式存储。方便插入、添加操作
字符串和数字:
在python里拷贝、赋值时地址都一样。理论上拷贝应该不一样,但是python内部做了优化,结果导致地址一样。
列表,元组,字典:
赋值
只是创建一个变量,该变量指向原来内存地址,如:
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]} n2 = n1
copy 浅复制 复制时只会复制父对象,而不会复制对象的内部的子对象。
deepcopy 深复制 复制对象及其子对象
In [55]: a = [11,22,33] In [56]: b = a In [57]: import copy In [58]: c = copy.deepcopy(a) In [59]: id(a) Out[59]: 139989431745672 In [60]: id(b) Out[60]: 139989431745672 In [61]: id(c) Out[61]: 139989482468296 In [62]: a.append(44) In [63]: a Out[63]: [11, 22, 33, 44] In [64]: b Out[64]: [11, 22, 33, 44] In [65]: c Out[65]: [11, 22, 33]
In [89]: a = [11,22,33] In [90]: b = [44,55,66] In [91]: c = [a,b] In [92]: e = copy.deepcopy(c) In [93]: c Out[93]: [[11, 22, 33], [44, 55, 66]] In [94]: e Out[94]: [[11, 22, 33], [44, 55, 66]] In [95]: a.append(66) In [96]: c Out[96]: [[11, 22, 33, 66], [44, 55, 66]] In [97]: e Out[97]: [[11, 22, 33], [44, 55, 66]]
集合
创建集合
s1 = set()
s = {11,22}
交集
py={'alex','lhf','123','546'} li={'alex',454,'lhf',552} print(py&li) print(py.intersection(li))
以上代码运行结果
{'lhf', 'alex'} {'lhf', 'alex'}
并集
py={'alex','lhf','123','546'} li={'alex',454,'lhf',552} print(py|li)
以上代码运行结果
{'546', 454, 552, 'alex', 'lhf', '123'}
差集
py里面存在,li里面不存在的
py={'alex','lhf','123','546'} li={'alex',454,'lhf',552} print(py-li) print(py.difference(li))
以上代码运行结果
{'123', '546'} {'123', '546'}
difference_update()
找s1中存在,s2中不存在的集合,更新自己
s1 = {1, 2, 3, 'fds', 4, 5, 65, 52}
s2 = {1, 2, 3}
print(s1.difference_update(s2))
print(s1)
以上代码运行结果
None
{65, 4, 5, 52, 'fds'}
对称差集
py={'alex','lhf','123','546'} li={'alex',454,'lhf',552} print(py^li)
print(py.symmetric_difference)
以上代码运行结果
{552, '546', '123', 454} {552, '546', '123', 454}
是否父集
s1={1,2,3,4,5} s2={1,2} print(s1>=s2) print(s2.issubset(s1))
以上代码运行结果
True
True
是否子集
s1={1,2,3,4,5} s2={1,2} print(s2<=s1) print(s1.issuperset(s2))
以上代码运行结果
True
True
将元组转换为集合
t1=(1,2,3) s1 = set(t1) print(s1)
以上代码运行结果
{1, 2, 3}
集合的其它内置方法
s1 = {1,2,3,'fds',4,5,65,52} s1.update('e') s1.update((1,2,3,4)) s2 ={'e','g',5} s1.update(s2) s1.update('hello') print(s1)
以上代码运行结果
{65, 2, 3, 4, 5, 1, 'e', 'h', 'g', 52, 'fds', 'o', 'l'}
增加
s1 = {1,2,3,'fds',4,5,65,52} s1.add('hello') print(s1)
以上代码运行结果
{65, 2, 3, 4, 5, 1, 'hello', 52, 'fds'}
随机删除(当所有元素为数字时不随机)
#!/usr/bin/env python # -*- coding: utf-8 -*- s1 = {1,2,3,'fds',4,5,65,52} s1.pop() print(s1)
以上代码运行结果
{2, 3, 4, 5, 1, 52, 'fds'}
指定删除
s1 = {1,2,3,'fds',4,5,'ggh',52} s1.remove(2) s1.remove(3) print(s1)
以上代码运行结果
{1, 4, 5, 'fds', 'ggh', 52}
不报错的删除
s1 = {1,2,3,'fds',4,5,'ggh',52} s1.discard('a') print(s1)
以上代码运行结果
{1, 2, 3, 'ggh', 4, 5, 'fds', 52}
文件处理
# open(文件名,模式,编码)
# 默认只读
打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。
打开文件的模式有:
- r ,只读模式【默认】
- w,只写模式【不可读;不存在则创建;存在则清空内容;】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【不可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】
- w+,写读【可读,可写】
- x+ ,写读【可读,可写】
- a+, 写读【可读,可写】
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型
指针
一、先介绍下file读入的控制函数:
seek(offset,where): where=0从起始位置移动,1从当前位置移动,2从结束位置移动。当有换行时,会被换行截断。seek()无返回值,故值为None。
# 将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了where参数就不一定了,where可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。
seek()的三种模式:
(1)f.seek(p,0) 移动当文件第p个字节处,绝对位置
(2)f.seek(p,1) 移动到相对于当前位置之后的p个字节
(3)f.seek(p,2) 移动到相对文章尾之后的p个字节
tell(): 返回文件的当前位置,即文件指针当前位置,以文件开头为原点,受seek、readline、read、readlines影响,不受truncate影响
r+
w,末尾追加,指针到最后,但是依然能读到最开始未读完的内容,例如:开始用f.read(1),1后面未读的内容依然在写入之后能读到,seek后,从当前指针位置往后写。
r,指针为0,起始位置
#!/usr/bin/env python # -*- coding: utf-8 -*- a = "abcd\ngsgdsf\ndsf" f1 = open("test.txt","w") f1.write(a) #查看当前指针位置 print(f1.tell()) f1.close() f2 = open("test.txt","r") content1 = f2.readline() print(content1) content2 = f2.readline() print(content2) #查看当前指针位置 print(f2.tell()) #调整指针到文件开头 f2.seek(0,0) #查看当前指针位置 print(f2.tell()) content3 = f2.readline() print(content3) f2.close()
普通方式打开:默认以utf-8解码打开
从文件上读出来的字节内容--->通过utf-8解码成字符串打开
f = open('new.txt', 'r',encoding='utf-8') data = f.read() f.close() print(data)
以普通方式写入:要写入特定编码的文本文件,请给open()
函数传入encoding
参数,将字符串自动转换成指定编码。
python默认以utf-8编码后写入,
如果想以gbk的方式写入,
方式一:以b方式打开,然后f.write(bytes('中国人',encoding='gbk')写入
方式二:给open()
函数传入encoding
参数,字符串将自动转换成指定编码。
f = open('h1.log','w',encoding='gbk) f.write('中国人') f.close()
以bytes方式打开:
从文件上读出来的字节内容,不需要进行utf-8解码,写入的时候要以字节方式写入
f = open('h1.log','wb') f.write(bytes('a',encoding='utf-8')) f.close() f = open('h1.log','rb') data = f.read() f.close() print(data,ord(data)) str_data = str(data,encoding='utf-8') print(str_data)
以上代码执行结果(这里b'a'里面的a,表现形式是a,本质上是二进制)
b'a' 97 a
对于 ASCII 字符串,可以直接使用 b'xxxx' 赋值创建 bytes 实例,
readline,只读取一行
readlines:读取所有行,放在一个列表里
truncate(num):截取文件前num个,会直接修改文件
flush:强行刷入硬盘
查看文件前五行(方法一)
f = open("file", encoding="utf-8") for index,line in enumerate(f.readlines()): if index < 5: print(line.strip()) else: break
f.close()
以上代码运行结果
1.周智明 2.周智明 3.周智明 4.周智明 5.周智明
查看文件前五行(方法二)
# !/usr/bin/env python # -*- coding: utf-8 -*- f = open("file", encoding="utf-8") for i in range(5): print(f.readline().strip())
f.close()
以上代码运行结果
1.周智明 2.周智明 3.周智明 4.周智明 5.周智明
查看文件前五行(方法三,推荐,前两种都会把前5行都读到内存,第三种只会读取一行到内存。)
# !/usr/bin/env python # -*- coding: utf-8 -*- f = open("file", encoding="utf-8") line_nu = 0 for line in f: if line_nu <5: print(line.strip()) line_nu +=1
f.close()
以上代码运行结果
1.周智明 2.周智明 3.周智明 4.周智明 5.周智明
大文件复制方法
#!/usr/bin/env python # -*- coding: utf-8 -*- old_file_name = input("请输入要复制的文件名:") #打开要复制的文件 old_file = open(old_file_name,"r") #为复件命名 position = old_file_name.rfind(".") new_file_name = old_file_name[:position] + "[复件]" + old_file_name[position:] #新建一个文件 new_file = open(new_file_name,"w") #从旧文件读取数据并写到新文件 while True: content = old_file.read(1024) if len(content)==0: break new_file.write(content) #关闭两个文件 old_file.close() new_file.close()
with open() as obj复制文件
可以同时打开多个文件,且操作完自动关闭
with open('h1.log','r',encoding='utf-8') as obj1, open('h2.log','w',encoding='utf-8') as obj2: for line in obj1: obj2.write(line)
利用文件处理实现验证用户登录:
db
admin$123
zzz$111
login.py
def login(username,passwd): ''' 用于验证登录 :param username: :param passwd: :return: True登录成功,False登录失败 ''' with open('db', 'r', encoding='utf-8') as f: for line in f: line = line.strip() line_list = line.split('$') # print(line_list) if username == line_list[0] and passwd == line_list[1]: return True return False def isregister(username): ''' 验证用户名是否注册 :param username: :return: ''' with open('db','r',encoding='utf-8') as f: for line in f: line = line.strip() line_list = line.split('$') if username == line_list[0]: return True return False def register(username,passwd): ''' 注册用户 :param username: :param passwd: :return: ''' with open('db','a',encoding='utf-8') as f: temp = '\n%s$%s'%(username,passwd) f.write(temp) return True def main(): ''' 登录主函数 :param username: :param passwd: :return: ''' choice =input('1、登录 2、注册>>') if choice == '1': username = input('请输入用户名') passwd = input('请输入密码') is_login = login(username,passwd) if is_login: print('登录成功') else: print('登录失败') elif choice == '2': username = input('请输入用户名') passwd = input('请输入密码') if isregister(username): print('用户已存在') return else: if register(username,passwd): print('注册成功') else: print('注册失败') main()
文件编码