【Python之路Day3】基础篇
今日目录:
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 以只读方式打开文件,文件指针将会放在文件开头的位置,这也是默认的模式;
-
#以只读模式打开文件,赋值给文件句柄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 以只写入的方式打开文件,如果文件存在内容,会清空文件后,再打开,文件指针在开头的位置。如果文件不存在,则创建新文件;
-
#至写入模式 >>> 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 打开文件以追加的模式,如果该文件存在,文件指针会放到文件末尾的位置,也就是说新的内容会将被写入到文件的末尾。如果文件不存在,创建新文件来写入。
-
# 追加方式 >>> 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;
-
# 先查看下文件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+ 读写模式打开文件,文件指针会在开头的位置;
-
#读写模式 >>> 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+模式 >>> 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+模式 >>> 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+模式,如果文件存在就会报错文件已经存在 >>> 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 二进制读模式打开文件,文件指针会放在文件的开头。
-
#先用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+模式 >>> 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模式写入一个二进制文件 >>> 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+模式还是会清空文件 >>> 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 二进制只写,如果文件存在报错?否则创建新文件?
-
# 文件存在还是会报错 >>> 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+ 二进制写读模式打开文件,如果存在覆盖,否则创建新文件。
-
# 如果存在文件,会报错 >>> 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,二进制只写模式 >>> 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+ 二进制写读模式打开,如果存在文件,文件指针在末尾,如果不存在,创建新文件。
-
>>> 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]]
传入的函数和在末尾追加的内容是同一个引用,所以结果是一样的。