zoukankan      html  css  js  c++  java
  • 【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}
    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 = '
    ' + 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 = '
    ' + 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('33[34;1m卧槽,碉堡了,土豪,我们朋友吧~33[0m')
                    print('-'*50)
            else:
                print('抱歉,您输入的 33[31;1m%s 33[0m不是一个合法的工资/金额'%User_salary)
    
        return User_salary
    
    def Deny_user(username):
        '''定义一个写入用户信息到黑名单的函数,在后面的时候调用直接将锁定用户信息写入到锁文件中去'''
        with open('db/locked.db','a+') as f:
            print('33[1;31m抱歉,用户 %s 输入次数太多, 已被锁定,请联系管理员解锁!' %username)
            f.write('%s
    ' %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('33[31;1m您的用户已经被锁定,请联系管理员解锁!33[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('33[32;1m欢迎登陆 %s33[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('33[32;1m欢迎您, %s, 您上一次的余额为 %s33[0m'%(k,user_info[user]['salary']))
                                print('购物车的内容如下'.center(70,'-'))
                                print('33[34;1m序列       宝贝名            数量      小计      购买时间33[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('33[33;1m请选择您感兴趣的分类  Q/q(退出程序) C/c(检查购物车)33[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('33[34;1m序列       宝贝名            数量      小计      购买时间33[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('33[34;1m亲爱的用户[ %s ], 共消费 [ %s ]元, 您的余额 [ %s ]元33[0m'%(user,user_consume,User_salary))
    
                if input('33[31;1m 按下任意键继续...33[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('33[33;1m请选择您需要的宝贝序列添加到购物车:  Q/q(退出程序) B/b(返回) C/c(检查购物车)33[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('您已经选择了宝贝33[32;1m %s 33[0m, 宝贝价格(元):33[32;1m %s 33[0m'%(product1,price))
                    product_num = input('请输入你欲购买的宝贝33[32;1m %s 33[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('恭喜你,成功购买宝贝33[32;1m %s 33[0m数量33[32;1m %s 33[0m,' 
                                  '此次消费33[32;1m %s (元) 33[0m, 余额:33[32;1m %s 33[0m' 
                                  %(product1,product_num,price,User_salary))
                            print('#'*70)
                            continue
                        else: #输入用户余额不足,提示用户充值
                            pay = input('33[31;1m抱歉,您的余额[ %s ],宝贝价格[ %s ],余额不足,不能购买此宝贝,是否充值? (y/Y)33[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('充值成功,账户最新余额:33[31;1m [ %s ] 元33[0m'%User_salary) #打印充值成功
                                    if User_salary >= 200000:  #如果用户充值金额大于等于20W,绝对是土豪身份
                                        print('33[34;1m卧槽,碉堡了,土豪,我们朋友吧~33[0m')
                                    print('-'*50)
                                    if input('按下任意键继续...'):pass
                                    continue
                                else:  #如果输入一个非y/Y值,提示用户没有选择充值,而后进入商品详单列表
                                    print('抱歉,您没有选择充值')
                                    continue
                    else:
                        #print('33[31;1m输入数量不可用!33[0m')
                        if input('33[31;1m抱歉,您输入数量的不可用!按下任意键继续...33[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('33[34;1m序列       宝贝名            数量      小计      购买时间33[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('33[34;1m亲爱的用户[ %s ], 共消费 [ %s ]元, 您的余额 [ %s ]元33[0m'%(user,user_consume,User_salary))
    
                    if input('33[32;1m 按下任意键继续...33[0m'):pass
                if User_id2 == 'b' or User_id2 == 'B':  #输入b/B,返回上一级
                    User_flag = True
                    break
                else:
                    #print('33[31;1m您输入的宝贝序列不可用!!!33[0m')
                    continue
    
                    #pass
                    #print(product1)
                    #print(price)
        else:
            if not User_id:
                print('33[31;1m您输入的宝贝序列不可用!!!33[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
      '
      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'xe6x88x91xe6x98xafxe8xb0x81?'
      >>> 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'xe5xb7xb4xe6x8bx89xe5xb7xb4xe9x98xbf'
      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 = '
      这是ab模式输入的内容'
      # 在文件尾部添加内容
      >>> f.write(s.encode('utf-8'))
      30
      # 关闭文件
      >>> f.close()
      ab 二进制只写模式
    •  ab+  二进制写读模式打开,如果存在文件,文件指针在末尾,如果不存在,创建新文件。
    • >>> f = open('test4.txt','ab+')
      >>> f.tell()
      85
      >>> s = '
      这是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'xe8xbfx99xe6x98xafxb+xe4xbax8cxe8xbfx9bxe5x88xb6xe5x86x99xe8xafxbbxe6xa8xa1xe5xbcx8fxefxbcx8cxe6x98xafpython3xe6x96xb0xe5xa2x9exe7x89xb9xe6x80xa7
      '
      b'xe8xbfx99xe6x98xafabxe6xa8xa1xe5xbcx8fxe8xbex93xe5x85xa5xe7x9ax84xe5x86x85xe5xaexb9
      '
      b'xe8xbfx99xe6x98xafab+xe6xb7xbbxe5x8axa0xe7x9ax84xe5x86x85xe5xaexb9'
      >>> 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
    ABC
    DEF'
    >>> f.seek(0)
    0
    # 一次只读取一行内容
    >>> f.readline()
    '1,2,3abc
    '
    >>> f.tell()
    9
    >>> f.seek(0)
    0
    # 可以指定读取的字节数
    >>> f.readline(3)
    '1,2'
    View Code

    readlines  读取所有数据,并根据换行符保存内容至列表

    >>> f.seek(0)
    0
    # 全部放在列表中
    >>> f.readlines()
    ['1,2,3abc
    ', 'ABC
    ', 'DEF']
    >>> f.seek(0)
    0
    #对列表可做进一步操作
    >>> f.readlines()[0]
    '1,2,3abc
    '
    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
    ABC
    DEFbalbalbalallla'
    View Code

    writelines  写内容,(列表)

    #写入字符串,也OK
    >>> f.writelines('这是啥我也不知道')
    >>> f.tell()
    54
    >>> f.read()
    ''
    >>> f.seek(0)
    0
    >>> f.read()
    
    '1,2,3abc
    ABC
    DEFbalbalbalallla这是啥我也不知道'
    # write写字符串也ok
    >>> s1 = 'daniel'
    >>> f.write(s1)
    6
    >>> f.writelines(s1)
    >>> f.seek(0)
    0
    >>> f.read()
    '1,2,3abc
    ABC
    DEFbalbalbalallla这是啥我也不知道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
    ', 'ABC
    ', 'DEFbalbalbalallla这是啥我也不知道danieldanieliamissupperman']
    >>> f.seek(0)
    0
    >>> f.read()
    '1,2,3abc
    ABC
    DEFbalbalbalallla这是啥我也不知道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
    ABC
    DEFbalbalbalallla这是啥我也不知道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
    ABC
    DEFbalbalbalallla这是啥我也不知道danieldanieliamissuppermanabcdk1k2'
    View Code

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

    >>> f.writable()
    True
    View Code

    tell  返回当前指针位置

    >>> f.tell()
    0
    View Code

    seek 移动指针位置

    >>> f.read()
    '1,2,3abc
    ABC
    DEF'
    >>> f.seek(3)
    3
    >>> f.read()
    ',3abc
    ABC
    DEF'
    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
    ABC
    DEFbalbalbalallla这是啥我也不知道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]]

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

      

       

  • 相关阅读:
    CoreBluetooth
    弹出照片选择器
    ios 去除UITextField中的空格
    ios UITableView默认选中第一行
    ios 监听设备旋转方向
    ios 添加朦层
    ios 异步加载图片
    ios 屏幕旋转的问题
    c# Socket通信基础
    ios 更改全局UINavigationBar的背景图片以及通知栏颜色
  • 原文地址:https://www.cnblogs.com/dubq/p/5520208.html
Copyright © 2011-2022 走看看