【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 = '\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]]

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

  

 

   

posted @ 2016-05-23 15:35  DBQ  阅读(507)  评论(0编辑  收藏  举报