dubq

今日目录:

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}
View Code

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
View Code

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
View Code

issuperset 是否是父集,是为True,否为False

>>> s4
{33, 11, 44, 22, 55}
>>> s5
{33, 11, 22}
>>> s4.issuperset(s5)  #s4是s5的父集合,返回True
True
View Code

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
动态参数-*args

** 传值的时候必须指定一个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\'>
动态参数-**args

   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\'
    r 只读模式
  • 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()
    w 只写模式
  • 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()
    a 追加模式
  • 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()
    x 只写模式

上面的这些模式都是要么只读、要么只写入,如果添加一个  “+”,就表示可以同时读写了:

  • 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()
    r+ 读写模式
  • 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()
    w+ 写读模式
  • 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()
    a+ 写读模式
  • 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()
    x+写读模式

以"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+  二进制只读模式打开文件,文件指针会放在文件的开头。
  • # 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\'
    rb+ 读写二进制模式
  •  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()
    wb+ 二进制写读模式
  •  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()
    xb+ 二进制写读模式
  •  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+添加的内容
    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\'
View Code

raw 查看文件句柄详细信息

>>> f.raw
<_io.FileIO name=\'test4.txt\' mode=\'ab+\'>

encoding 查看编码

>>> f.encoding
\'UTF-8\'
View Code

close  关闭文件句柄

>>> f.close()

read  读取指定字节数据,如果不指定值,则返回整个文件内容

>>> f.read()
\'1,2,3abc\'
>>> f.read(3)
\'1,2\'
View Code

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\'
View Code

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\'
View Code

readable  文件是否可读,可读返回True,否则返回False

>>> f = open(\'test.txt\',\'r+\')
>>> f.readable()
True
>>> f.close()
>>> f = open(\'test.txt\',\'a\')
>>> f.readable()
False
View Code

write 写内容(字符串)

>>> f.write(\'balbalbalallla\')
14
>>> f.seek(0)
0
>>> f.read()
\'1,2,3abc\nABC\nDEFbalbalbalallla\'
View Code

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\'
View Code

writable 是否可写,可写返回True,否则返回False

>>> f.writable()
True
View Code

tell  返回当前指针位置

>>> f.tell()
0
View Code

seek 移动指针位置

>>> f.read()
\'1,2,3abc\nABC\nDEF\'
>>> f.seek(3)
3
>>> f.read()
\',3abc\nABC\nDEF\'
View Code

seekable 指针是否可读,是: True, 否:False, Python3新增

>>> f.seekable()
True
View Code

fileno  返回一个文件的文件描述符,可以用在os模块的read方法等一些底层的操作

>>> f.fileno()
3
View Code

isatty  判断文件是否连接在一个终端设备,是:true,否:False

>>> f.isatty()
False
View Code

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()
View Code

flush  刷写文件内部缓存,直接把缓冲区的数据立即写入文件,而不是被动的等待缓冲区写入。

>>> f.flush()
View Code
 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
View Code

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
View Code

七. 全局变量

全局变量遵循名称全部大写的规范,即:

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
View Code
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
global后再修改

全局变量如果是列表类型,在函数里可以增、删、修改,但是不能重新赋值,否则将会重新开辟一个内存地址,在函数里定义了一个同名的局部变量而已。

#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]]

传入的函数和在末尾追加的内容是同一个引用,所以结果是一样的。

  

 

   

分类:

技术点:

相关文章: