今日目录:
1. set
2. 函数
3. 内置函数
4. 文件操作
5. 三元运算
6. lambda表达式
7. 全局变量
一. set
set是Python基本数据类型中的一种,主要特性是: 无序、不重复的序列,基本功能包括关系测试(如父集子集等)、消除重复的元素等。set集合还支持difference(差集)、intersection(交集)、union(联合)、sysmmetric difference(对称差集)等数学运算。学习set还是按照两步骤来:1.创建 2.功能
1. 创建set集合
>>> s = set(\'daniel\') >>> s {\'d\', \'n\', \'e\', \'l\', \'i\', \'a\'} >>> type(s) <class \'set\'>
或者:
>>> s1 = {\'a\',\'b\',\'c\',}
>>> s1
{\'a\', \'c\', \'b\'}
>>> type(s1)
<class \'set\'>
注意如果要创建一个空集合,必须使用set()了,s={} 默认的是字典类型,需要使用s=set()才行
>>> s1 = {} >>> type(s1) <class \'dict\'> >>> s1 = set() >>> type(s1) <class \'set\'> >>>
可以试着尝试下传入一个列表进去:
>>> l1 = [1,2,3,4,5,5,4,3,2,1,1,2,3,4,5] >>> s4 = set(l1) >>> s4 {1, 2, 3, 4, 5} #可以看到set的不重复特性
2. 操作方法
add 往set里添加元素
>>> s1 {1, 2, 3, 4, 5} >>> s1.add(6) >>> s1 {1, 2, 3, 4, 5, 6} #add()方法一次只能接受一个参数,也就是只能添加一个元素到set里 >>> s1.add(7,8,9) #一次加3个会报错 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: add() takes exactly one argument (3 given) #通过字符串形式添加,看能否一次添加多个 >>> l3=\'789abc\' >>> s1.add(l3) >>> s1 {1, 2, 3, 4, 5, 6, \'789abc\'} #也是把一个字符串当成一个参数来添加
clear 清空set
>>> s1 {1, 2, 3, 4, 5, 6, \'789abc\'} >>> s1.clear() >>> s1 set()
copy 复制
>>> s1 {1, 2, 3, 4, 5, 6, \'789abc\'} >>> s2 = s1.copy() >>> id(s1) 139851744274920 >>> id(s2) 139851744275368
difference 取差集
>>> s1 = {1,3,4,5,}
>>> s2 = {3,1,7,9}
>>> s1.difference(s2) #A里有的元素,B里没有的元素
{4, 5}
intersection 取交集
>>> s1 = {1,3,4,5,}
>>> s2 = {3,1,7,9}
>>> s1.intersection(s2) #A和B都有的元素
{1, 3}
symmetric_difference 对称差集
>>> s1 = {1,3,4,5,}
>>> s3 = {11,22,3,4}
>>> s1.symmetric_difference(s3) #A中有,B没有,B有,A没有的元素
{1, 5, 11, 22}
difference_update intersection_update symmetric_difference_update 这三个放在一起说,主要是带update会更新原始数据:
>> s1 {1, 3, 4, 5} >>> s2 {9, 1, 3, 7} >>> s1.difference_update(s2) >>> s1 #s1的值已经变成了s1和s2的交集的结果 {4, 5} >>> s2 #s2的值没变 {9, 1, 3, 7} #intersection_update >>> s2 {9, 1, 3, 7} >>> s3 {3, 4, 11, 22} >>> s2.intersection_update(s3) >>> s2 #s2的值变成两个交集的结果 {3} >>> s3 #s3不变 {3, 4, 11, 22} #symmetric_difference_update >>> s3 {3, 4, 11, 22} >>> s4 {3, 44, 11, 22, 55} >>> s3.symmetric_difference_update(s4) >>> s3 #取两个集合的对称差集写入到s3中了 {4, 55, 44} >>> s4 #s4不变 {3, 44, 11, 22, 55}
discard 如果set中存在某元素,就删除
>>> s1 {4, 5} >>> s1.discard(60) #set中没有60元素,所以没返回任何消息 >>> s1 {4, 5} >>> s1.discard(5) #set中有元素5,所以,元素被删除 >>> s1 {4}
pop 删除元素,set是无序的,因此也是随机删除元素,但是会返回删除的这个元素值,pop的特性,在Python的数据类型中都是这种,删除后会返回这个删除元素;
>>> s4 {3, 44, 11, 22, 55} >>> s4.pop() 3 >>> s4.pop(55) >>> s4.pop() 44
remove 删除指定的元素,必须要返回一个值
>>> s4 {11, 22, 55} >>> s4.remove(44) #由于set中没有44元素,所以报错 Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 44 >>> s4.remove(55) #删除55元素 >>> s4 {11, 22}
issubset 是否是子集,是为True,否为False
>>> s3 {4, 55, 44} >>> s4 {33, 11, 44, 22, 55} >>> s3.issubset(s4) #s3不是s4的子集,返回为False False >>> s4.issubset(s3) False >>> s5 = {11,22,33} >>> s5.issubset(s4) #s5是s4的子集,返回True True
issuperset 是否是父集,是为True,否为False
>>> s4 {33, 11, 44, 22, 55} >>> s5 {33, 11, 22} >>> s4.issuperset(s5) #s4是s5的父集合,返回True True
union 联合,数据可以是字符串、list、dict、int任意类型,并且会把元素拆开,去重之后添加到set中,但是,如果需要保存的话,应该赋值给一个变量
>>> l1 = [1,2,3,4,5,] #创建一个列表 >>> s3 #查看s3以前元素 {4, 55, 44} >>> s3.union(l1) #将l1中的每一个元素遍历,并加入到sets中打印出来 {1, 2, 3, 4, 5, 44, 55} >>> s3 #s3中的元素还是没有变,所以如需保存,应该赋值给变量 {4, 55, 44} >>> str1=\'daniel\' #创建一个字符串 >>> s3.union(str1) #union会将字符串拆分,去重后加入set打印 {4, \'l\', 44, \'i\', 55, \'a\', \'n\', \'e\', \'d\'} >>> t1 = (3,4,5,6,) #tuple一样 >>> s3.union(t1) {3, 4, 5, 6, 44, 55} >>> t1 = (3,4,5,6,99,0,234,441,34,) >>> s3.union(t1) {0, 34, 3, 4, 5, 6, 99, 234, 44, 55, 441} >>> d1 = {\'k1\':\'v1\',\'k2\':\'v2\',\'k3\':[1,3,3,4,55,]} #字典默认会遍历所有key然后加入到set打印 >>> s3.union(d1) {\'k3\', \'k2\', 4, 55, 44, \'k1\'}
update,和union一样,都是扩充/添加元素到set,唯一不同的是update会写入原有集合中,而union不会
>>> s1=\'daniel\' #先创建一个字符串 >>> s2 = {\'a\',\'b\',\'c\'} #含有abc元素的set >>> s2 {\'a\', \'c\', \'b\'} >>> s2.update(s1) #加入元素s1 >>> s2 {\'l\', \'c\', \'b\', \'i\', \'a\', \'n\', \'e\', \'d\'} #结果是直接写入到s2的set中 >>> l1 = [1,2,23,4,5,6,] >>> s2 {\'l\', \'c\', \'b\', \'i\', \'a\', \'n\', \'e\', \'d\'} >>> s2.update(l1) >>> s2 {1, 2, 4, \'l\', \'c\', 5, 6, \'b\', \'i\', 23, \'a\', \'n\', \'e\', \'d\'}
isdisjoin 判断两个set中是否有交集,有返回True,否则返回False
>>> s2 {1, 2, 4, \'l\', \'c\', 5, 6, \'b\', \'i\', 23, \'a\', \'n\', \'e\', \'d\'} >>> s3 {4, 55, 44} >>> s2.isdisjoint(s3) False
3. 练习题
寻找差异
#需求: #如下数据,假设是一个CMDB,老的数据库中的数据(内存槽位): old_dic = { \'#1\': 8, \'#2\': 4, \'#4\': 2, } #新采集的数据, new_dic = { \'#1\': 4, \'#2\': 4, \'#3\': 2, } # 槽位1,槽位2值发生变化需要更新数据到老的数值 # 槽位4发生变化,已经移除,需要删除数据 # 槽位3发生变化,新增槽位,需要插入记录
old_dic = { \'#1\': 8, \'#2\': 4, \'#4\': 2, } new_dic = { \'#1\': 4, \'#2\': 4, \'#3\': 2, } #将新老数值的key值取出,并转换成set类型 old_dic1 = set(old_dic.keys()) new_dic1 = set(new_dic.keys()) #A和B取差集,找到要删除的槽位 print(\'要删除的槽位是: %s\' %old_dic1.difference(new_dic1)) #A和B取交集,找到需要更新的槽位 print(\'要更新的槽位是: %s\' %old_dic1.intersection(new_dic1)) #B和A取差集,找到要插入的槽位 print(\'要增加的槽位为: %s\' %new_dic1.difference(old_dic1))
二. 函数
函数说白了就是一组代码集合,用于在程序中反复调用,解决代码重复编写的问题。两天的作业中,基本上都是堆积代码实现的,第二天的购物车程序更是码了近400行,根据作业需求逻辑从上到下一步一步码代码,一个打印功能就写了四处代码,而且一旦修改重复功能的话,所有的地方都要修改。这个是面向过程的编程方式。如果用到函数的话,代码首先变的很简洁,另外,review代码的人也比较容易看懂代码,毕竟程序不是一个人来编写的,即便是一个人编写的,过几天作者都有可能忘记自己写的代码段的功能了,所以函数式编程+良好的注释是一个很好的习惯和修养。
如下一个实例,验证用户登录身份,1:登录程序 2: 注册用户,如果用到面向过程编程的话,代码看起来是介样子的:
user_input_num = input(\'1. 登录程序 2.注册用户\').strip() if user_input_num == \'1\': user_input_name = input(\'请输入用户名:\').strip() user_input_pass = input(\'请输入密码:\').strip() with open(\'user.db\',\'r\') as f: for line in f: if user_input_name == line.strip().split()[0] and user_input_pass == line.strip().split()[1]: print(\'登录成功\') break else: print(\'登录失败,用户名或者密码错误\') if user_input_num == \'2\': user_input_name = input(\'请输入用户名:\').strip() user_input_pass = input(\'请输入密码:\').strip() with open(\'user.db\',\'r+\') as f: for line in f: if user_input_name == line.strip().split()[0]: print(\'用户名太抢手,已经被注册啦\') else: user_info = \'\n\' + user_input_name + \' \' + user_input_pass f.write(user_info) print(\'%s,恭喜你,注册成功\' %user_input_name)
而使用函数式编程是这样的:
def login(username,password): \'\'\' 用户登录程序 :param username:接受用户输入的用户名 :param password: 接受用户输入的密码 :return: True:表示认证成功,False:表示认证失败 \'\'\' #with open(\'user.db\',\'r\') as f: f = open(\'user.db\',\'r\') for line in f.readlines(): if line.strip().split()[0] == username and line.strip().split()[1] == password: return True else: return False def registry(user,passwd): \'\'\' 用户注册函数 :param user: 接受用户传入注册用的用户名 :param passwd: 接受用户传入的注册密码 :return: 如果用户不存在,并且写入用户名到文件成功后返回True,否则返回False \'\'\' with open(\'user.db\',\'r+\') as f: for line in f: if user == line.strip().split()[0]: return True else: info = \'\n\' + user + \' \' + passwd f.write(info) return False def main(): user_select = input(\'1:登录程序, 2:注册用户\').strip() if user_select == \'1\': username = input(\'请输入用户名:\').strip() password = input(\'请输入密码:\').strip() r = login(username,password) if r: print(\'登录成功\') else: print(\'登录失败,用户名或密码错误\') if user_select == \'2\': user_input_name = input(\'请输入用户名:\').strip() passwd_input = input(\'请输入密码:\').strip() R = registry(user_input_name,passwd_input) if R: print(\'用户名太抢手,已经被注册了!\') else: print(\'注册成功!\') if __name__ == \'__main__\': main()
好吧,这个例子不太明显,因为代码量少,看看我写的第二天的作业购物车程序例子吧:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) \'\'\' Author: DBQ Blog: http://www.cnblogs.com/dubq/articles/5497639.html Github: https://github.com/daniel-vv/ops \'\'\' import time import sys import os import pickle import getpass def User_Input_salary(): \'\'\' 定义一个函数,用于接收用户输入工资金额 \'\'\' Flag = False while not Flag: User_salary = input(\'请输入您预消费的金额(元):\').strip() if User_salary.isdigit(): User_salary=int(User_salary) Flag = True if User_salary >= 200000: print(\'-\'*50) print(\'\033[34;1m卧槽,碉堡了,土豪,我们朋友吧~\033[0m\') print(\'-\'*50) else: print(\'抱歉,您输入的 \033[31;1m%s \033[0m不是一个合法的工资/金额\'%User_salary) return User_salary def Deny_user(username): \'\'\'定义一个写入用户信息到黑名单的函数,在后面的时候调用直接将锁定用户信息写入到锁文件中去\'\'\' with open(\'db/locked.db\',\'a+\') as f: print(\'\033[1;31m抱歉,用户 %s 输入次数太多, 已被锁定,请联系管理员解锁!\' %username) f.write(\'%s\n\' %username) #定义一个字典,用于下面验证用户身份,账户名密码通过key:value的形式存储在字典中 user_list = { \'tom\':\'123\', \'jerry\':\'123\', \'jack\':\'123\', } def username(): \'\'\' 定义一个函数,用于接收用户输入用户名密码的验证 如果用户名在锁定文件locked.db中,直接返回给用户已被锁定,退出程序 判断用户输入是否是同一用户输入三次错误尝试,如果是,则锁定用户,否则三次之后退出程序; \'\'\' Flag = False Count = 0 Lock_count = 1 user_name = \'\' while Count < 3: User_input_name = input(\'请输入您的用户名: \').strip() if User_input_name: User_input_name = str(User_input_name) User_input_pass = getpass.getpass(\'请输入您的密码: \').strip() with open(\'db/locked.db\',\'r\') as f: for i in f: if User_input_name == i.strip(): print(\'\033[31;1m您的用户已经被锁定,请联系管理员解锁!\033[0m\') exit(0) if User_input_name == user_name: Lock_count += 1 else: user_name = User_input_name Lock_count -= 1 for user,passwd in user_list.items(): if User_input_name == user and User_input_pass == passwd: #判断用户名和密码认证是否成功 print(\'\033[32;1m欢迎登陆 %s\033[0m\'.center(50,\'#\') %User_input_name) Flag = True break if Flag: break else: print(\'用户名或密码不正确,请重新输入\') #print(User_input_name) #print(User_input_pass) Count += 1 ##if User_input_name if Flag: break else: if Lock_count == 2: Deny_user(User_input_name) exit(0) #user_info.remove(User_input_name) #if len(data) != 0: #del user_info[User_input_name] #return User_input_name,user_info,User_salary #else: #return User_input_name return User_input_name ##定义商品列表 commodity_list = { \'家电类\':{ \'西门子冰箱\':4998, \'美的空调\':3912, \'微波炉\':1248, \'饮水机\':328, \'乐视 Max70\':9979, \'小米电视 \':4199, \'洗衣机\':3328, \'格力空调\':2889, \'MacBook Pro\':10899, \'高压力锅\':399, \'电磁炉\':198, \'净水器\':1999, \'滤水壶\':599, }, \'图书类\':{ \'小姨多鹤\':37.9, \'向着光明那方\':29.9, \'百年孤独\':39.9, \'了不起的盖茨比\':21.8, \'扶桑(严歌苓)\':32.8, \'陆犯焉识\':39.8, \'孩子你慢慢来\':25.8, \'鱼羊野史套装\':146.8, \'明朝那些事儿\':166.7, \'活着(余华作品)\':15.6, \'皮囊(蔡崇达)\':21.8, \'目送(龙应台)\':23.8, \'三体(国内最牛x科幻)\':188, \'失乐园\':33.0, }, \'衣服类\':{ \'棒球帽\':99, \'T恤\':199, \'皮带\':299, \'Adidas鞋\':899, \'Nike鞋\':899, \'Puma鞋\':768, \'皮鞋\':699, \'Lee牛仔裤\':409, \'内裤\':49, \'运动袜\':29, \'休闲西服上\':499, \'七分裤\':249, \'休闲家居服\':199, \'匡威双肩包\':269, \'仿古蛤蟆镜\':298, \'鞋垫\':38, }, \'手机类\':{ \'iPhone 6s 16G\':4987, \'iPhone 6s 64G\':5688, \'iPhone 6sP 16G\':6088, \'iPhone 6sP 64G\':6888, \'锤子坚果\':899, \'小米Max\':1999, \'Samsung S7\':5688, \'华为P9\':3688, \'魅族MX5\':1999, \'Nexus6\':3300, }, \'汽车类\':{ \'宝马 7\':1200000, \'宝马 5\':660000, \'宝马 3\':380000, \'Tesla ModelS\':790000, \'速腾\':160000, \'迈腾\':210000, \'甲壳虫\':250000, \'高尔夫\':180000, \'卡罗拉\':130000, \'迈锐宝\':150000, \'凯美瑞\':210000, }, \'烟酒类\':{ \'玉溪\':22, \'中华\':45, \'利群\':14, \'南京\':13, \'芙蓉王\':19, \'白沙\':10, \'苁蓉\':13, \'云烟\':11, \'长白山\':11, \'老白汾\':398, \'白玉汾酒\':198, \'玫瑰汾酒\':298, \'五粮液\':499, \'衡水老白干\':198, \'茅台\':399, \'梦之蓝\':398, \'郎酒\':398, \'天之蓝\':298, }, } user_shopping_db = \'db/user_shopping.db\' shopp_car = \'{0} {1} {2} {3} {4}\' #user_file = open(user_shopping_db,\'rb\') data = open(user_shopping_db,\'rb\').read() if len(data) != 0: user_data = len(pickle.load(open(user_shopping_db,\'rb\'))) user_info = pickle.load(open(user_shopping_db,\'rb\')) else: user_data = 0 user_shopping = {} #定义一个空字典,用于存储用户的购物车信息 Flag = False #定义标志位,用于进入循环 User_flag = False #定义一个用户标志位,用于判断用户是否有认证,防止后面循环会要求用户反复认证 while not Flag: #进入循环主题 if not User_flag: #根据定义用户标志位来判断 user = username() #将上面定义函数实例化,并赋值给user变量 if user_data != 0: #判断变量非空进入下面验证,取出用户上一次登录程序 for i in user_info.keys(): if user == i: id = 1 for k,v in user_info.items(): if user == k: #shopp_car = \'{0} {1} {2} {3} {4}\' print(\'\033[32;1m欢迎您, %s, 您上一次的余额为 %s\033[0m\'%(k,user_info[user][\'salary\'])) print(\'购物车的内容如下\'.center(70,\'-\')) print(\'\033[34;1m序列 宝贝名 数量 小计 购买时间\033[0m\') #先打印title User_salary = user_info[user][\'salary\'] del user_info[user][\'salary\'] for k1,v1 in user_info[user].items(): if user != k1: print(shopp_car.format(id,k1,v1[0],v1[1],v1[2],)) id +=1 #continue else: print(\'-\'*70) #if input(\'按下任意键继续...\'):pass #del user_info[user] user_shopping = user_info else: User_salary = User_Input_salary() pass else: User_salary = User_Input_salary() #实例化用户输入消费金额函数并复制给变量 print(\'~Bingo, 欢迎 [ %s ] 来到 DBQ 的百货店,请选择您需要的宝贝以及数量,祝您购物愉快~\'.center(70,\'#\')%user) for id,keys in enumerate(commodity_list.keys()): #进入三级菜单 print(id,keys) User_id = input(\'\033[33;1m请选择您感兴趣的分类 Q/q(退出程序) C/c(检查购物车)\033[0m\').strip() if User_id == \'q\' or User_id == \'Q\': #判断是Q/q,退出程序 print(\'欢迎下次再来 [ %s ], bye!\'%user) Flag = True break if User_id == \'c\' or User_id == \'C\': #如果是c/C,检查用户购物车,如果购物车为空,提示用户为空 if len(user_shopping) != 0: #判断如果用户购物车不为空是显示购物车信息 print(\'购物车\'.center(70)) print(\'-\'*70) print(\'\033[34;1m序列 宝贝名 数量 小计 购买时间\033[0m\') #先打印title product_index = 1 #定义一个序列ID user_consume = 0 #定义一个值为0的用户消费金额初始值,用于下面累加用户此次消费总金额 #print(user_shopping) for value in user_shopping[user].keys(): #print(value) #print(shopp_car.format(product_index,index,value[1][0],value[0][1],value[0][2],)) print(shopp_car.format(product_index,value,user_shopping[user][value][0],user_shopping[user][value][1],user_shopping[user][value][2],)) user_consume += user_shopping[user][value][1] #自增用户消费金额 product_index += 1 #序列ID自增 print(\'-\'*70) print(\'\033[34;1m亲爱的用户[ %s ], 共消费 [ %s ]元, 您的余额 [ %s ]元\033[0m\'%(user,user_consume,User_salary)) if input(\'\033[31;1m 按下任意键继续...\033[0m\'):pass else: #如果购物车为空,提示用户购物车为空,并返回商品列表 print(\'-\'*50) print(\'抱歉,你还未购买任何宝贝,购物车里空到不行不行的~\') print(\'-\'*50) if User_id.isdigit() and int(User_id) < len(commodity_list.keys()): product = list(commodity_list.keys())[int(User_id)] #将字典转换为有序列表 while not Flag: for id2,key2 in enumerate(commodity_list[product].items()): #进入商品明细,供用户选择序号购买 print(id2,key2) print(\'#\'*70) User_id2 = input(\'\033[33;1m请选择您需要的宝贝序列添加到购物车: Q/q(退出程序) B/b(返回) C/c(检查购物车)\033[0m\'.center(30,\'#\')).strip() if User_id2.isdigit() and int(User_id2) < len(commodity_list[product]): #print(commodity_list[product][int(User_id2)]) product1 = list(commodity_list[product].keys())[int(User_id2)] price = int(commodity_list[product][product1]) print(\'您已经选择了宝贝\033[32;1m %s \033[0m, 宝贝价格(元):\033[32;1m %s \033[0m\'%(product1,price)) product_num = input(\'请输入你欲购买的宝贝\033[32;1m %s \033[0m数量:\'%product1).strip() if product_num.isdigit() and product_num and int(product_num) != 0: product_num = int(product_num) price *= product_num if price <= User_salary: User_salary -= price product_time = time.strftime(\'%Y-%m-%d %H:%M:%S\',time.localtime()) #返回当前购买时间给一个变量 #if product1 not in user_shopping.get(user): #判断如果用户购买的商品不在购物车中直接setdefault值为新商品信息 if not user_shopping.get(user): #user_shopping[user]= #user_shopping[user] = [{product1,[product_num,price,product_time,]}] user_shopping[user] = {product1:[product_num,price,product_time,]} else: #如果存在购物车中,更新现有信息 #print(user_shopping[user][product1][0][0]) user_shopping[user].setdefault(product1,[product_num,price,product_time,]) print(user_shopping) product_num += user_shopping[user][product1][0] #累加商品数量 print(user_shopping[user][product1][0]) price += user_shopping[user][product1][1] #累加商品金额 user_shopping[user][product1][0] = product_num #重新修改购物车中的值 user_shopping[user][product1][1] = price user_shopping[user][product1][2] = product_time #user_shopping[product_id] = [product1,product_num,price,product_time] #打印购买成功信息,包括用户购买商品\金额以及余额 print(\'恭喜你,成功购买宝贝\033[32;1m %s \033[0m数量\033[32;1m %s \033[0m,\' \ \'此次消费\033[32;1m %s (元) \033[0m, 余额:\033[32;1m %s \033[0m\' \ %(product1,product_num,price,User_salary)) print(\'#\'*70) continue else: #输入用户余额不足,提示用户充值 pay = input(\'\033[31;1m抱歉,您的余额[ %s ],宝贝价格[ %s ],余额不足,不能购买此宝贝,是否充值? (y/Y)\033[0m\'%(User_salary,price)).strip() if pay and pay == \'y\' or pay == \'Y\': #输入y/Y为确认充值 pay_money = input(\'请输入要充值的金额:\').strip() #充值金额 if pay_money.isdigit() and int(pay_money) != 0: #如果是数字而且充值金额不能为0 User_salary += int(pay_money) #用户余额+=新充值金额,并赋值给余额变量 time.sleep(1) print(\'-\'*50) print(\'充值成功,账户最新余额:\033[31;1m [ %s ] 元\033[0m\'%User_salary) #打印充值成功 if User_salary >= 200000: #如果用户充值金额大于等于20W,绝对是土豪身份 print(\'\033[34;1m卧槽,碉堡了,土豪,我们朋友吧~\033[0m\') print(\'-\'*50) if input(\'按下任意键继续...\'):pass continue else: #如果输入一个非y/Y值,提示用户没有选择充值,而后进入商品详单列表 print(\'抱歉,您没有选择充值\') continue else: #print(\'\033[31;1m输入数量不可用!\033[0m\') if input(\'\033[31;1m抱歉,您输入数量的不可用!按下任意键继续...\033[0m\'):pass continue if User_id2 == \'q\' or User_id2 == \'Q\': #输入Q/q,退出程式 #user_shopping[user].setdefault(user,User_salary) #退出之前将用户名和用于余额信息写入字典用于下一次登录判断 user_shopping[user].setdefault(\'salary\',User_salary) with open(user_shopping_db,\'wb\') as f: #f.write(str(user_shopping.items())) pickle.dump(user_shopping,f) print(\'欢迎下次再来 [ %s ], bye!\'%user) time.sleep(1) Flag = True break if User_id2 == \'c\' or User_id2 == \'C\': #允许用户输入c/C查看购物车信息 print(\'购物车\'.center(70)) print(\'-\'*70) print(\'\033[34;1m序列 宝贝名 数量 小计 购买时间\033[0m\') #先打印title product_index = 1 #定义一个序列ID user_consume = 0 #定义一个值为0的用户消费金额初始值,用于下面累加用户此次消费总金额 #print(user_shopping) for value in user_shopping[user].keys(): #print(value) #print(shopp_car.format(product_index,index,value[1][0],value[0][1],value[0][2],)) print(shopp_car.format(product_index,value,user_shopping[user][value][0],user_shopping[user][value][1],user_shopping[user][value][2],)) user_consume += user_shopping[user][value][1] #自增用户消费金额 product_index += 1 #序列ID自增 print(\'-\'*70) print(\'\033[34;1m亲爱的用户[ %s ], 共消费 [ %s ]元, 您的余额 [ %s ]元\033[0m\'%(user,user_consume,User_salary)) if input(\'\033[32;1m 按下任意键继续...\033[0m\'):pass if User_id2 == \'b\' or User_id2 == \'B\': #输入b/B,返回上一级 User_flag = True break else: #print(\'\033[31;1m您输入的宝贝序列不可用!!!\033[0m\') continue #pass #print(product1) #print(price) else: if not User_id: print(\'\033[31;1m您输入的宝贝序列不可用!!!\033[0m\') User_flag = True continue else: User_flag = True
如果要修改一个功能非常费劲,可如果用到函数式编程的话,代码可读性等等一大堆好处就来了
还没时间重写啦
1.函数的组成:
def f1(a,b): pass return # def 定义函数的关键字 # f1 函数名,可以是任何字符串合法的字符,但不能是Python内部保留字 # a,b 参数,主要为函数体提供数据 # () 固定搭配 # pass 函数体 # return 返回值,默认情况下如果不显式指定return值的话,Python会返回为None,这和其他语言不太一样;
2.返回值
定义了一个函数,在程序里引用,所以函数应该将执行的结果返回一个参数,好让调用者继续执行下面的逻辑。还是那个登陆程序的例子,可以用汉字写出来看看:
def 登陆函数(等待用户传入用户名,密码): pass 打开文件,赋值给一个变量,并且循环遍历文件内容 if 如果用户名和文件中的用户名匹配,并且提供的密码和文件中的密码匹配 #打印登陆成功 return True 返回一个True 如果验证失败 return False def 主函数(): 用户输入序列,选择是登陆还是注册用户 如果是登陆 提示用户输入用户名\密码 R = 调用上面登陆函数(用户输入用户名,密码) 调用登陆函数, 并将结果复制给变量R if R为True 打印登陆成功 else 否则 打印用户名密码验证失败: ...
主函数()
3. 参数
函数参数的作用有多大,不用多言了吧,总之太重要了。如果没有参数的话,函数将会变的很不灵活
函数中有几种不同的参数:
1. 普通参数
#定义一个函数f1,接受用户传入参数name,而后在函数体内打印用户输入的值。name叫做形式参数 >>> def f1(name): ... print(name) ... #调用函数,并传入一个值,这里的值daniel叫做实际参数; >>> f1(\'daniel\') daniel
2. 默认参数
#定义一个函数f2,接受用户输入两个形式参数,并给形式参数指定一个默认值 >>> def f2(name,job=\'devops\'): ... print(name,job) ... #调用函数,并使用默认参数,‘devops’ >>> f2(\'daniel\') daniel devops
3. 指定参数
#定义一个函数f3,接受用户输入两个形参,并给定age一个默认参数为18 >>> def f3(name,age=18): ... print(\'Name: %s, Age: %s\'%(name,age)) ... #调用参数,明确指定一个age参数为17 >>> f3(\'daniel\',17) Name: daniel, Age: 17
4. 动态参数
动态参数有两种,一种是一个*,一种是 **
* 默认接受N个参数,并将用户传入的实际参数放到元组里面,默认情况下都用 *args表示形参
#定义一个函数f4, 接受形参*args >>> def f4(*args): ... print(args) ... print(type(args)) ... print(*args) ... print(type(*args)) ... #定义一个列表l1 >>> l1=[1,2,3,4,5,] #调用函数,将l1赋值给函数 >>> f4(l1) ([1, 2, 3, 4, 5],) #默认方式是将一个列表当做整体元素包含在元组内 <class \'tuple\'> [1, 2, 3, 4, 5] #在函数体内打印*args是转换成原有的数据类型 <class \'list\'> #再定义一个t1的元组,一个name的字符串,一个t2的字典 >>> t1=(5,4,3,2,1,) >>> name=(\'daniel\') >>> t2 = {\'k1\':\'v1\',\'k2\':\'v2\'} #重新定义函数 >>> def f4(*args): ... print(args) ... print(type(args)) ... print(*args) ... #调用函数,并把字典、列表、元组、字符串都复制进去,看看变化 >>> f4(l1,t1,name,t2) #默认函数体里打印args,是把添加的任意个元组当成元组内的一个元素 ([1, 2, 3, 4, 5], (5, 4, 3, 2, 1), \'daniel\', {\'k2\': \'v2\', \'k1\': \'v1\'}) <class \'tuple\'> #在函数体内打印*args,是将用户传入的实体参数还原为本来的数据类型,即字符串就是字符串,而字典还是字典... [1, 2, 3, 4, 5] (5, 4, 3, 2, 1) daniel {\'k2\': \'v2\', \'k1\': \'v1\'} #还有一个玩法,可以在调用函数传入实体参数的时候,在前面加* >>> f4(*l1,*t1,*name,*t2) #这个玩法,在默认函数体内打印传入形参值,会是遍历传入的参数,而后赋值给元组内 (1, 2, 3, 4, 5, 5, 4, 3, 2, 1, \'d\', \'a\', \'n\', \'i\', \'e\', \'l\', \'k2\', \'k1\') <class \'tuple\'> #而*args是会还原原有的数据类型,去掉元组,个人感觉没卵用; 1 2 3 4 5 5 4 3 2 1 d a n i e l k2 k1
** 传值的时候必须指定一个key和value,默认是字典类型;默认使用 **kwargs表示形参
#定义函数f5,接受用户传入形参**kwargs def f5(**kwargs): print(kwargs) print(type(kwargs)) #调用函数时,第一种赋值方式 f5(Name=\'daniel\',Age=18,Job=\'IT\') {\'Name\': \'daniel\', \'Job\': \'IT\', \'Age\': 18} <class \'dict\'> #定义一个字典t1 t1 = {\'Name\':\'daniel\',\'Age\':18,\'Job\':\'IT\'} #调用函数第二种赋值方式,实在实参前面加** f5(**t1) {\'Age\': 18, \'Name\': \'daniel\', \'Job\': \'IT\'} <class \'dict\'>
5. 万能参数
直白来说,就是两种动态参数的组合,需要注意的是两种动态参数组合使用时,*必须放在第一个位置,否则会报错
#定义函数f6,接受形参*args,**kwargs,在函数体内打印两个值,和数据类型 def f6(*args,**kwargs): print(args,kwargs) print(type(args)) print(type(kwargs)) #调用函数,前面是*,后面是** f6(\'我是谁?\',\'几年几岁?\',\'做什么工作?\',Name=\'Daniel\',Age=18,Job=\'IT\') (\'我是谁?\', \'几年几岁?\', \'做什么工作?\') {\'Age\': 18, \'Name\': \'Daniel\', \'Job\': \'IT\'} <class \'tuple\'> <class \'dict\'> #也可以这么玩: t1 = {\'Name\':\'daniel\',\'Age\':18,\'Job\':\'IT\'} f6(\'我是谁?\',\'几年几岁?\',\'做什么工作?\',**t1) (\'我是谁?\', \'几年几岁?\', \'做什么工作?\') {\'Name\': \'daniel\', \'Age\': 18, \'Job\': \'IT\'} <class \'tuple\'> <class \'dict\'> #尝试下把**放在前面: t1 = {\'Name\':\'daniel\',\'Age\':18,\'Job\':\'IT\'} f6(**t1,\'我是谁?\',\'几年几岁?\',\'做什么工作?\') f6(**t1,\'我是谁?\',\'几年几岁?\',\'做什么工作?\') ^ SyntaxError: positional argument follows keyword argument unpacking #直接报语法错误: #在函数体内把**kwargs放在前面试下: def f6(**kwargs,*args): print(args,kwargs) print(type(args)) print(type(kwargs)) #执行还是报错语法错误 def f6(**kwargs,*args): ^ SyntaxError: invalid syntax
三. Python内嵌函数
内置函数主要是使用比较频繁的或者是元操作,所以Python通过内置函数的方式提供
四. 文件操作
在Python3里提供了open函数来对文件操作,Python2中有file函数 。
1. open()函数语法
使用open函数的语法:
file object = open(file_name [, access_mode][, buffering])
file object: 文件句柄,在后面通过此句柄对该文件操作等等;
file_name: 文件名称,如果不在当前目录下,需要制定绝对/相对路径
access_mode: 打开模式,表示允许对文件操作的权限等
buffering:如果值为0,就不会有寄存。如果为1,访问文件时会寄存。如果值设定大于1的整数,说明这就是寄存区的大小。如果取负值,寄存区的缓冲大小则为系统默认。
2. 打开文件模式:
- r 以只读方式打开文件,文件指针将会放在文件开头的位置,这也是默认的模式;
-
r 只读模式
#以只读模式打开文件,赋值给文件句柄f >>> f = open(\'test.txt\',\'r\') # 写入数据尝试,报错,是只读的,不允许写! >>> f.write(\'abc\') Traceback (most recent call last): File "<stdin>", line 1, in <module> io.UnsupportedOperation: not writable # 查看文件指针位置,可以看到在文件开头的位置; >>> f.tell() 0 # 读取文件内容 >>> f.readline() \'abc\n\'
- w 以只写入的方式打开文件,如果文件存在内容,会清空文件后,再打开,文件指针在开头的位置。如果文件不存在,则创建新文件;
-
w 只写模式
#至写入模式 >>> f = open(\'test.txt\',\'w\') #查看文件指针,在文件首部 >>> f.tell() 0 #不允许读 >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in <module> io.UnsupportedOperation: not readable #写入文件1,2,3,会覆盖之前文件里的abc内容,并返回当前的文件指针位置 >>> f.write(\'1,2,3\') 5 #验证下文件指针位置 >>> f.tell() 5 #结束后一定不要忘记关闭文件 >>> f.close()
- a 打开文件以追加的模式,如果该文件存在,文件指针会放到文件末尾的位置,也就是说新的内容会将被写入到文件的末尾。如果文件不存在,创建新文件来写入。
-
a 追加模式
# 追加方式 >>> f = open(\'test.txt\',\'a\') # 文件指针在文件末尾的位置,即旧内容后面 >>> f.tell() 5 #读文件报错 >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in <module> io.UnsupportedOperation: not readable # 写入文件后,返回写入内容后指针后移的位置,并非实际指针位置 >>> f.write(\'abc\') 3 # 查看文件指针,还是在文件最尾部 >>> f.tell() 8 # 关闭文件 >>> f.close()
- x Python3里新添加的模式,以只写入的方式打开文件,文件内容如果存在会报错,否则则创建新文件。一般建议,写入时使用x而不用w;
-
x 只写模式
# 先查看下文件test.txt里的内容 >>> f = open(\'test.txt\',\'r\') >>> f.read() \'1,2,3abc\' >>> f.close() # 以x模式打开文件,直接报错文件存在,错误代码17 >>> f = open(\'test.txt\',\'x\') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileExistsError: [Errno 17] File exists: \'test.txt\' # 重新打开一个不存在的文件: >>> f = open(\'test1.txt\',\'x\') #指针模式在文件首部 >>> f.tell() 0 # 写入5个字符,文件指针在5的位置 >>> f.write(\'abcde\') 5 # 返回指针位置 >>> f.tell() 5 # 在写入内容123,返回指针移动位置 >>> f.write(\'123\') 3 # 返回指针位置,8 >>> f.tell() 8 # 一定不要忘记关闭文件句柄 >>> f.close()
上面的这些模式都是要么只读、要么只写入,如果添加一个 “+”,就表示可以同时读写了:
- r+ 读写模式打开文件,文件指针会在开头的位置;
-
r+ 读写模式
#读写模式 >>> f = open(\'test1.txt\',\'r+\') # 默认文件指针在文件首部 >>> f.tell() 0 # 读取文件内容 >>> f.read() \'abcde123\' #文件指针跑到文件尾部去了 >>> f.tell() 8 # 写入,就成了尾部追加了 >>> f.write(\'新增加\') 3 # 一个汉字三个三个指针 >>> f.tell() 17 # 再读取,已经空了,因为文件指针已经走到最后面了 >>> f.read() \'\' # 用seek将指针调整到文件头部 >>> f.seek(0) 0 # 在读取 >>> f.read() \'abcde123新增加\' >>> f.close()
- w+ 写读模式打开文件,如果文件里有内容,就会覆盖,否则的话,会创建新文件,使用场景还是不多;
-
w+ 写读模式
#W+模式 >>> f = open(\'test1.txt\',\'w+\') # 默认文件句柄在文件首部 >>> f.tell() 0 # 写入文件 >>> f.write(\'w+模式\') 4 #获取指针位置 >>> f.tell() 8 #后面已经无内容了,所以为空 >>> f.read() \'\' # 重置文件指针到首部 >>> f.seek(0) 0 # 读取文件内容,看到源文件内容已经被清空了 >>> f.read() \'w+模式\' >>> f.close()
- a+ 写读模式打开文件,如果存在,文件指针会放在文件的结尾。文件打开时会是追加模式,如果不存在会创建新的文件;
-
a+ 写读模式
# a+模式 >>> f = open(\'test1.txt\',\'a+\') # 默认文件指针在文件尾部 >>> f.tell() 8 # 所以读取为空 >>> f.read() \'\' # 写入a+模式内容 >>> f.write(\'a+模式内容\') 6 # 返回指针位置 >>> f.tell() 22 # 将指针重置到开始位置 >>> f.seek(0) 0 # 读取,可以看到上一步w+的内容还在 >>> f.read() \'w+模式a+模式内容\' >>> f.close()
- x+ 写读模式打开文件,
-
x+写读模式
# x+模式,如果文件存在就会报错文件已经存在 >>> f = open(\'test1.txt\',\'x+\') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileExistsError: [Errno 17] File exists: \'test1.txt\' #打开一个不存在的文件 >>> f = open(\'test2.txt\',\'x+\') #模式文件指针在文件首部 >>> f.tell() 0 # 写入文件内容 >>> f.write(\'x+模式\') 4 #返回文件指针 >>> f.tell() 8 #在写入 >>> f.write(\'balabala\') 8 #读取为空,文件指针在尾部 >>> f.read() \'\' #重置指针 >>> f.seek(0) 0 >>> f.read() \'x+模式balabala\' #关闭文件 >>> f.close()
以"b"表示以二进制的方式操作,需要注意的是以"b"方式打开文件是字节类型,写入时也需要提供自己类型,反之一样。
- rb 二进制读模式打开文件,文件指针会放在文件的开头。
-
rb 二进只读模式
#先用wb模式写入一个二进制文件 >>> f = open(\'test2.txt\',\'wb\') #定义一个中文字符串 >>> s1 = \'我是谁?\' #写入时,使用utf-8编码 >>> f.write(s1.encode(\'utf-8\')) 10 >>> f.tell() 10 #关闭文件 >>> f.close() #用rb模式打开一个文件 >>> f = open(\'test2.txt\',\'rb\') #试着用默认编码读取,看到是b(二进制格式) >>> f.read() b\'\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81?\' >>> f.tell() 10 #重置指针到文件首部 >>> f.seek(0) 0 # 将f.read() 复制给一个变量 >>> r = f.read() # 而后使用decode将字符编码使用utf-8 >>> print(r.decode(\'utf-8\')) 我是谁? >>> f.close()
- rb+ 二进制只读模式打开文件,文件指针会放在文件的开头。
-
rb+ 读写二进制模式
# rb+模式 >>> f = open(\'test2.txt\',\'rb+\') >>> s = \'巴拉巴阿\' # 文件指针在文件首部 >>> f.tell() 0 #写入内容,并使用utf-8编码 >>> f.write(s.encode(\'utf-8\')) 12 # 返回文件指针 >>> f.tell() 12 # 重置指针 >>> f.seek(0) 0 >>> s = f.read() # 使用decode utf-8 编码读取文件 >>> print(s.decode(\'utf-8\')) 巴拉巴阿 >>> f.tell() 12 >>> f.seek(0) 0 # 直接读取显示无法显示 >>> f.read() b\'\xe5\xb7\xb4\xe6\x8b\x89\xe5\xb7\xb4\xe9\x98\xbf\'
- wb 二进制的只写模式打开文件,如果文件存在会清空文件,否则创建新文件。
-
wb 二进只写模式
#用wb模式写入一个二进制文件 >>> f = open(\'test2.txt\',\'wb\') #文件指针默认在文件首部,会清空原有文件 >>> f.tell() 0 #定义一个中文字符串 >>> s1 = \'我是谁?\' #写入时,使用utf-8编码 >>> f.write(s1.encode(\'utf-8\')) 10 >>> f.tell() 10 #关闭文件 >>> f.close()
- wb+ 二进制写读模式,如果文件存在会覆盖文件,否则会创建新文件。
-
wb+ 二进制写读模式
# wb+模式还是会清空文件 >>> f = open(\'test2.txt\',\'wb+\') # 默认文件指针位置在首部 >>> f.tell() 0 >>> s = f.read() >>> print(s.decode(\'utf-8\')) >>> s1 = \'这模式怎么又清空文件啦?\' >>> f.write(s1.encode(\'utf-8\')) 36 >>> f.tell() 36 >>> f.seek(0) 0 >>> s = f.read() >>> print(s.decode(\'utf-8\')) 这模式怎么又清空文件啦? >>> f.close()
- xb 二进制只写,如果文件存在报错?否则创建新文件?
-
xb 二进制只写模式
# 文件存在还是会报错 >>> f = open(\'test2.txt\',\'xb\') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileExistsError: [Errno 17] File exists: \'test2.txt\' # 如果不存在的话,操作和wb一样 >>> f = open(\'test2.txt\',\'xb\') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileExistsError: [Errno 17] File exists: \'test2.txt\' >>> f = open(\'test3.txt\',\'xb\') >>> s = \'这是xb二进制只写入模式,是python3新增\' >>> f.tell() 0 >>> f.write(s.encode(\'utf-8\')) 51 >>> f.tell() 51 >>> f.seek(0) 0 # 不允许读取 >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in <module> io.UnsupportedOperation: read >>> f.close()
- xb+ 二进制写读模式打开文件,如果存在覆盖,否则创建新文件。
-
xb+ 二进制写读模式
# 如果存在文件,会报错 >>> f = open(\'test3.txt\',\'xb+\') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileExistsError: [Errno 17] File exists: \'test3.txt\' >>> f = open(\'test4.txt\',\'xb+\') >>> f.tell() 0 >>> s = \'这是xb+二进制写读模式,是python3新增特性\' # 可写入 >>> f.write(s.encode(\'utf-8\')) 55 # 也可读写 >>> s1 = f.read() >>> print(s1.decode(\'utf-8\')) 这是xb+二进制写读模式,是python3新增特性 >>> f.close()
- ab 二进制追加模式打开文件,如果存在文件,文件指针在末尾,文件打开时会是追加模式,新内容在旧内容之后,如果文件不存在,创建新文件来写入。
-
ab 二进制只写模式
# ab,二进制只写模式 >>> f = open(\'test4.txt\',\'ab\') # 默认文件指针在文件尾部 >>> f.tell() 55 # 不允许读 >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in <module> io.UnsupportedOperation: read >>> s = \'\n这是ab模式输入的内容\' # 在文件尾部添加内容 >>> f.write(s.encode(\'utf-8\')) 30 # 关闭文件 >>> f.close()
- ab+ 二进制写读模式打开,如果存在文件,文件指针在末尾,如果不存在,创建新文件。
-
ab+ 二进制写读模式
>>> f = open(\'test4.txt\',\'ab+\') >>> f.tell() 85 >>> s = \'\n这是ab+添加的内容\' >>> f.write(s.encode(\'utf-8\')) 25 >>> f.tell() 110 >>> f.seek(0) 0 #也可以使用for循环逐行读取,并复制给s,而后使用decode进行解码 >>> for line in f: ... s = line ... print(s) ... b\'\xe8\xbf\x99\xe6\x98\xafxb+\xe4\xba\x8c\xe8\xbf\x9b\xe5\x88\xb6\xe5\x86\x99\xe8\xaf\xbb\xe6\xa8\xa1\xe5\xbc\x8f\xef\xbc\x8c\xe6\x98\xafpython3\xe6\x96\xb0\xe5\xa2\x9e\xe7\x89\xb9\xe6\x80\xa7\n\' b\'\xe8\xbf\x99\xe6\x98\xafab\xe6\xa8\xa1\xe5\xbc\x8f\xe8\xbe\x93\xe5\x85\xa5\xe7\x9a\x84\xe5\x86\x85\xe5\xae\xb9\n\' b\'\xe8\xbf\x99\xe6\x98\xafab+\xe6\xb7\xbb\xe5\x8a\xa0\xe7\x9a\x84\xe5\x86\x85\xe5\xae\xb9\' >>> f.seek(0) 0 >>> for line in f: ... s = line ... print(line.decode(\'utf-8\').strip()) ... 这是xb+二进制写读模式,是python3新增特性 这是ab模式输入的内容 这是ab+添加的内容
3. 操作方法
还记得上面的每次打开文件后都需要close()吧,一个文件被打开后,可以使用方法来查看各种文件的信息
closed 如果返回为True表示文件已关闭,否则为False
>>> f.closed False >>> f.close() >>> f.closed True
mode 查看文件打开的模式
>>> f = open(\'test4.txt\',\'ab+\') >>> f.mode \'ab+\'
name 文件名
>>> f.name \'test4.txt\'
raw 查看文件句柄详细信息
>>> f.raw <_io.FileIO name=\'test4.txt\' mode=\'ab+\'>
encoding 查看编码
>>> f.encoding \'UTF-8\'
close 关闭文件句柄
>>> f.close()
read 读取指定字节数据,如果不指定值,则返回整个文件内容
>>> f.read() \'1,2,3abc\' >>> f.read(3) \'1,2\'
readline 仅读取一行数据,可以指定读取的字节数
# 文件内容三行 >>> f.read() \'1,2,3abc\nABC\nDEF\' >>> f.seek(0) 0 # 一次只读取一行内容 >>> f.readline() \'1,2,3abc\n\' >>> f.tell() 9 >>> f.seek(0) 0 # 可以指定读取的字节数 >>> f.readline(3) \'1,2\'
readlines 读取所有数据,并根据换行符保存内容至列表
>>> f.seek(0) 0 # 全部放在列表中 >>> f.readlines() [\'1,2,3abc\n\', \'ABC\n\', \'DEF\'] >>> f.seek(0) 0 #对列表可做进一步操作 >>> f.readlines()[0] \'1,2,3abc\n\'
readable 文件是否可读,可读返回True,否则返回False
>>> f = open(\'test.txt\',\'r+\') >>> f.readable() True >>> f.close() >>> f = open(\'test.txt\',\'a\') >>> f.readable() False
write 写内容(字符串)
>>> f.write(\'balbalbalallla\') 14 >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla\'
writelines 写内容,(列表)
#写入字符串,也OK >>> f.writelines(\'这是啥我也不知道\') >>> f.tell() 54 >>> f.read() \'\' >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道\' # write写字符串也ok >>> s1 = \'daniel\' >>> f.write(s1) 6 >>> f.writelines(s1) >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道danieldaniel\' #来试下列表 >>> l1 = [\'i\',\'am\',\'is\',\'supperman\'] # write失败 >>> f.write(l1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: must be str, not list # writelines没问题 >>> f.writelines(l1) >>> f.seek(0) 0 >>> f.readlines() [\'1,2,3abc\n\', \'ABC\n\', \'DEFbalbalbalallla这是啥我也不知道danieldanieliamissupperman\'] >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道danieldanieliamissupperman\' #来试下元组 >>> t1 = (\'a\',\'b\',\'c\',\'d\') >>> f.write(t1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: must be str, not tuple # writelines 是ok的 >>> f.writelines(t1) >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道danieldanieliamissuppermanabcd\' #测试下字典 >>> d1 = {\'k1\':\'v1\',\'k2\':\'v2\'} >>> f.write(d1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: must be str, not dict # writelines 还是ok的 >>> f.writelines(d1) >>> f.seek(0) 0 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道danieldanieliamissuppermanabcdk1k2\'
writable 是否可写,可写返回True,否则返回False
>>> f.writable()
True
tell 返回当前指针位置
>>> f.tell()
0
seek 移动指针位置
>>> f.read() \'1,2,3abc\nABC\nDEF\' >>> f.seek(3) 3 >>> f.read() \',3abc\nABC\nDEF\'
seekable 指针是否可读,是: True, 否:False, Python3新增
>>> f.seekable()
True
fileno 返回一个文件的文件描述符,可以用在os模块的read方法等一些底层的操作
>>> f.fileno()
3
isatty 判断文件是否连接在一个终端设备,是:true,否:False
>>> f.isatty()
False
truncate 截断文件,截取的字节通过参数提供,默认为当前指针位置
>>> f.tell() 0 #看下所有文件内容 >>> f.read() \'1,2,3abc\nABC\nDEFbalbalbalallla这是啥我也不知道danieldanieliamissuppermanabcdk1k2\' #再把指针指向开始位置 >>> f.seek(0) 0 # 截取三个字符 >>> f.truncate(3) 3 #查看文件指针 >>> f.tell() 0 # 查看文件 >>> f.read() \'1,2\' >>> f.read() \'\' >>> f.seek(0) 0 >>> f.read() \'1,2\' >>> f.seek(0) 0 #如果不提供参数,从当前默认的指针位置开始截取,当前为开始位置,所以清空文件内容 >>> f.truncate() 0 >>> f.read() \'\' >>> f.seek(0) 0 >>> f.read()
flush 刷写文件内部缓存,直接把缓冲区的数据立即写入文件,而不是被动的等待缓冲区写入。
>>> f.flush()
buffer = property(lambda self: object(), lambda self, v: None, lambda self: None) # default closed = property(lambda self: object(), lambda self, v: None, lambda self: None) # default encoding = property(lambda self: object(), lambda self, v: None, lambda self: None) # default errors = property(lambda self: object(), lambda self, v: None, lambda self: None) # default line_buffering = property(lambda self: object(), lambda self, v: None, lambda self: None) # default name = property(lambda self: object(), lambda self, v: None, lambda self: None) # default newlines = property(lambda self: object(), lambda self, v: None, lambda self: None) # default _CHUNK_SIZE = property(lambda self: object(), lambda self, v: None, lambda self: None) # default _finalizing = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
4. 管理上下文
上面的文件操作,打开操作完成之后每次都需要关闭文件,为了避免忘记,可以通过(with)管理上下文:
with open(\'test.txt\',\'r+\') as f: #打开test.txt文件以r+模式,并别名为f,操作完成后内部会自动关闭并释放文件资源 pass
另外在python2.7以后,with也支持同事打开两个文件来操作:
with open(\'test.txt\',\'r\') as f1, open(\'test2.txt\',\'w\') as f2: pass
五. 三元运算
三元运算又叫三目运算,主要是一些简单if else语句的缩写;先写判断条件 而后进入判断 最后条件不满足的操作:
>>> a = 1 >>> print(\'这是条件为真打印的结果\') if a == 1 else \'这是条件为假打印的结果\' 这是条件为真打印的结果 >>> a = 0 >>> print(\'这是条件为真打印的结果\') if a == 1 else \'这是条件为假打印的结果\' 这是条件为假打印的结果
>>> a = 1 if b != 3 else 4 >>> a 4
# 如果条件成立那么 a = 1 ,否则 a = 4
六. lambda表达式
Python lambda 实在python中使用lambda来创建匿名函数,而用def创建的方法是有函数名称的。看看lambda的精简格式吧:
lambda args: print(args)
#一个参数 >>> info = lambda a: a**3 >>> type(info) <class \'function\'> >>> info(2) 8 >>> info(4) 64 #两个参数 >>> m = lambda a,b: a*b >>> m(2,3) 6 >>> m(19,13) 247 #三个参数 >>> m = lambda x,y,z: (x-y)*z >>> m(3,2,1) 1 >>> m(3,2,2) 2 >>> m(3,2,3) 3 >>> m(3,3,3) 0 >>> m(3,22,3) -57
七. 全局变量
全局变量遵循名称全部大写的规范,即:
NAME = \'daniel\'
AGE = 18
JOB = \'IT\'
全局变量在所有的作用域都可以读;
NAME = {\'Name\':\'Daniel\'} def f1(): age = 18 print(NAME,age) print(id(NAME)) def f2(): age = 19 print(NAME,age) print(id(NAME)) def f3(): age = 17 print(NAME,age) print(id(NAME)) f1() f2() f3()
全局变量可以在函数里可读,也可以写,但是更改要在函数里使用global声明,不过不建议这么做!
#全局变量 NAME = {\'Name\':\'Daniel\'} def f1(): age = 18 print(NAME,age) print(id(NAME)) def f2(): age = 19 NAME=\'F2\' print(NAME,age) print(id(NAME)) def f3(): age = 17 print(NAME,age) print(id(NAME)) f1() f2() f3() 执行结果,在f2函数是修改了NAME值,但是这只是一个名字叫NAME的一个局部变量而已; {\'Name\': \'Daniel\'} 18 4321829832 F2 19 4323767664 {\'Name\': \'Daniel\'} 17 4321829832
NAME = {\'Name\':\'Daniel\'}
def f1():
age = 18
print(NAME,age)
print(id(NAME))
def f2():
age = 19
global NAME
NAME=\'F2\'
print(NAME,age)
print(id(NAME))
def f3():
age = 17
print(NAME,age)
print(id(NAME))
f1()
f2()
f3()
#执行结果
{\'Name\': \'Daniel\'} 18
4321829832
F2 19
4323767664
F2 17
4323767664
全局变量如果是列表类型,在函数里可以增、删、修改,但是不能重新赋值,否则将会重新开辟一个内存地址,在函数里定义了一个同名的局部变量而已。
#NAME = {\'Name\':\'Daniel\'} NAME=[\'a\',\'b\',\'c\',] def f1(): age = 18 print(NAME,age) print(id(NAME)) def f2(): age = 19 NAME[1] = \'B\' del NAME[0] NAME.append(\'D\') print(NAME,age) print(id(NAME)) def f3(): age = 17 print(NAME,age) print(id(NAME)) f1() f2() f3() #执行结果 [\'a\', \'b\', \'c\'] 18 4315828296 [\'B\', \'c\', \'D\'] 19 4315828296 [\'B\', \'c\', \'D\'] 17 4315828296
在python中,strings, tuple, 和number 是不可更改的对象,而list,dict等则是可以修改的对象。
Python中所有的参数(自变量)在python里都是按引用传递的,如果在函数里修改了参数,那么在调用这个参数的函数里,原始的参数也就改变了。
l1 = [10,20,30] def f1(value): value.append([1,2,3,4,5,]) print(\'函数内的引用值: %s\' %value) f1(l1) print(\'函数外列表值: %s\' %l1) #执行结果: 函数内的引用值: [10, 20, 30, [1, 2, 3, 4, 5]] 函数外列表值: [10, 20, 30, [1, 2, 3, 4, 5]]
传入的函数和在末尾追加的内容是同一个引用,所以结果是一样的。