Python20-Day03

##########文件操作相关##########

一、文件操作

  文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。

  文件操作的流程:

    * 打开文件,得到文件句柄并赋值给一个变量

    * 通过句柄对文件进行操作

    * 关闭文件

  python中的文件操作:

    1. 打开文件,得到文件句柄并赋值给一个变量

      f = open('a.txt','r',encoding='utf-8') #默认打开模式就为r

    2. 通过文件句柄对文件进行操作

      data = f.read()

    3. 关闭文件

      f.close()

  python的资源回收

    打开一个文件包含两部分资源:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:

    1、f.close() #回收操作系统级打开的文件
    2、del f #回收应用程序级的变量

    操作完毕文件后,一定要f.close()

  

  with关键字来帮助管理上下文:

  with open('a.txt','r',encoding='utf-8') as f:

    pass

  

二、打开文件的模式

  文件句柄 = open('文件路径','模式')

  模式可以是以下方式以及他们之间的组合:

Character Meaning
‘r' open for reading (default)
‘w' open for writing, truncating the file first
‘a' open for writing, appending to the end of the file if it exists
‘b' binary mode
‘t' text mode (default)
‘+' open a disk file for updating (reading and writing)
‘U' universal newline mode (for backwards compatibility; should not be used in new code)

  1. 打开文件的模式(默认为文本模式)

  r,只读模式 默认模式 文件必须存在,不存在抛出异常

  w,只写模式,不可读,不存在创建,存在则清空内容

  a,追加模式 不可读,不存在则创建,存在只增加内容

  2. 对于非文本文件,只能使用b模式,"b"表示以字节的方式操作,所有文件都是以字节的形式存储的,使用这种模式无序考虑文本文件的字符编码,

    rb wb ab

三、操作文件的方法:

  

#掌握
f.read() #读取所有内容,光标移动到文件末尾
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中

f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333\n','444\n']) #文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式

#了解
f.readable() #文件是否可读
f.writable() #文件是否可读
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
f.name

 

练习,利用b模式,编写一个cp工具,要求如下:

  1. 既可以拷贝文本又可以拷贝视频,图片等文件

  2. 用户一旦参数错误,打印命令的正确使用方法,如usage: cp source_file target_file

  提示:可以用import sys,然后用sys.argv获取脚本后面跟的参数

import sys

if len(sys.argv) != 3:
    print('usage: cp source_file target_file')
# source_file,target_file = sys.argv[1],sys.argv[2]
_,source_file,target_file = sys.argv
with open(source_file,'rb') as read_f,open(target_file,'wb') as write_f:
    for line in read_f:
        write_f.write(line)

 

四、文件修改

  方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

import os
with open('a.txt','r') as read_f,open('.a.txt.swap','w') as write_f:
    data = read_f.read()
    data = data.replace('1111','zhaoliying')
    write_f.write(data)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

 

  方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件

  

import os
with open('a.txt','r') as read_f,open('.a.txt.swap','w') as write_f:
    data = read_f.read()
    data = data.replace('1111','zhaoliying')
    write_f.write(data)
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')

 

 

练习题:

1. 文件a.txt内容:每一行内容分别为商品名字,价钱,个数,求出本次购物花费的总钱数
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3

 

goods_price_all = 0
with open('a.txt','r') as f:
    for line in f:
        line_list = line.split()
        price = int(line_list[1])
        goods_num = int(line_list[2])
        goods_price = price * goods_num
        goods_price_all+=goods_price
print('',goods_price_all)

 

##########函数相关##########

 

一、函数基础

  1、函数分类

    (1)内置函数:如len(),max(),sum()

    (2)自定义函数

  2、定义函数

    自定义函数的语法  

#语法
def 函数名(参数1,参数2,参数3,...):
    '''注释'''
    函数体
    return 返回的值

#函数名要能反映其意义

    函数使用的原则:先定义,再调用

#测试一
def foo():
    print('from foo')
    bar()
foo() #报错

#测试二
def bar():
    print('from bar')
def foo():
    print('from foo')
    bar()
foo() #正常

#测试三
def foo():
    print('from foo')
    bar()
    
def bar():
    print('from bar')
foo() #会报错吗?


#结论:函数的使用,必须遵循原则:先定义,后调用
#我们在使用函数时,一定要明确地区分定义阶段和调用阶段

#定义阶段
def foo():
    print('from foo')
    bar()
def bar():
    print('from bar')
#调用阶段
foo()

    函数在定义阶段都做了什么?

    只检查语法,不执行代码,也就是说,语法错误在函数定义阶段就会检测出来,而代码的逻辑只有在执行时才会知道

    2、 定义函数的3中形式

      1. 无参 :应用场景仅仅只是执行一些操作,比如用户交互,打印

      2. 有参: 需要根据外部传来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值

      3. 空函数: 涉及代码结构

#定义阶段
def tell_tag(tag,n): #有参数
    print(tag*n)

def tell_msg(): #无参数
    print('hello world')

#调用阶段
tell_tag('*',12)
tell_msg()
tell_tag('*',12)

'''
************
hello world
************
'''

#结论:
#1、定义时无参,意味着调用时也无需传入参数
#2、定义时有参,意味着调用时则必须传入参数

 

    3、调用函数

      1. 调用函数

        函数名加括号

        1 先找到名字

        2 根据名字调用代码

      2. 函数返回值

        无 return --> None

        return 1个值 -> 返回1个值

        return 逗号分隔多个值,元组

        什么时候该有返回值?

          调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值,通常有参函数需要有返回值,输入参数,经过计算,得到一个最终结果。

        什么时候不需要有返回值?

          调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需又返回值。通常无参函数不需要有返回值

      3. 函数调用的三种形式

        1 语句形式:foo()

        2 表达式形式: 3*len('hello')

        3 当中另外一个函数的参数:range(len('hello'))

      4. 函数的参数

        1 形参与实参

          形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定。

        2 具体应用

#1、位置参数:按照从左到右的顺序定义的参数
        位置形参:必选参数
        位置实参:按照位置给形参传值

#2、关键字参数:按照key=value的形式定义的实参
        无需按照位置为形参传值
        注意的问题:
                1. 关键字实参必须在位置实参右面
                2. 对同一个形参不能重复传值

#3、默认参数:形参在定义时就已经为其赋值
        可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
        注意的问题:
                1. 只在定义时赋值一次
                2. 默认参数的定义应该在位置形参右面
                3. 默认参数通常应该定义成不可变类型


#4、可变长参数:
        可变长指的是实参值的个数不固定
        而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs

        ===========*args===========
        def foo(x,y,*args):
            print(x,y)
            print(args)
        foo(1,2,3,4,5)

        def foo(x,y,*args):
            print(x,y)
            print(args)
        foo(1,2,*[3,4,5])


        def foo(x,y,z):
            print(x,y,z)
        foo(*[1,2,3])

        ===========**kwargs===========
        def foo(x,y,**kwargs):
            print(x,y)
            print(kwargs)
        foo(1,y=2,a=1,b=2,c=3)

        def foo(x,y,**kwargs):
            print(x,y)
            print(kwargs)
        foo(1,y=2,**{'a':1,'b':2,'c':3})


        def foo(x,y,z):
            print(x,y,z)
        foo(**{'z':1,'x':2,'y':3})

        ===========*args+**kwargs===========

        def foo(x,y):
            print(x,y)

        def wrapper(*args,**kwargs):
            print('====>')
            foo(*args,**kwargs)

#5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
可以保证,传入的参数中一定包含某些关键字
        def foo(x,y,*args,a=1,b,**kwargs):
            print(x,y)
            print(args)
            print(a)
            print(b)
            print(kwargs)

        foo(1,2,3,4,5,b=3,c=4,d=5)
        结果:
            1
            2
            (3, 4, 5)
            1
            3
            {'c': 4, 'd': 5}
  #1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作
  
import sys
import os
if len(sys.argv) != 4:
    print('Uasge: 函数 文件名 修改前 修改后')

# change_file = sys.argv[1]
# before_content = sys.argv[2]
# after_content = sys.argv[3]
change_file,before_content,after_content=sys.argv[1],sys.argv[2],sys.argv[3]

def change(change_file,before_content,after_content):
    with open(change_file,'r') as read_f,open('%s.swap' % change_file,'w') as write_f:
        for line in read_f:
            if before_content in line:
                line = line.replace(before_content,after_content)
            write_f.write(line)
change(change_file,before_content,after_content)

os.remove(change_file)
os.rename('%s.swap' %change_file,change_file)
  #2、写函数,计算传入字符串中【数字】、【字母】、【空格】 以及 【其他】的个数
def calc_num(calc_str):
    digit_num = 0
    space_num = 0
    zimu_num = 0
    other_num = 0
    for item in calc_str:
        if item.isdigit():
            digit_num=digit_num+1
        elif item.isspace():
            space_num=space_num+1
        elif item.isalpha():
            zimu_num=zimu_num+1
        else:
            other_num=other_num+1
    print(digit_num,zimu_num,space_num,other_num)
calc_num('helloworld123123132   321312    %%%%%% 321213 fadsfasf 4123412 ')
  #3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5
def object_len(object_user):
    if len(object_user) > 5:
        print('%s is 大于5' % object_user)
    else:
        print('其他')
# object_len('zhaoliying')
# object_len((11,111,22))

 

  #4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
def list_len(in_list):
    if not isinstance(in_list,list):
        print('%s is not list' % (in_list))
    else:
        # print('%s is list' % in_list)
        if len(in_list) > 2:
            in_list = in_list[0:2]
    return in_list
# print(list_len([1,2,3,4,5]))
# a = list_len([1,2,3,4,5])
# list_len([1,2,3,4,5])
  #5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者 
new_list = ['a','b','c','d','e','f','g','h','i',]
print(new_list[1::2])

def user_list(in_list):
    if not isinstance(in_list, list):
        print('%s is not list.' %in_list)
    else:
        print('%s is list.' %in_list)
        new_list=in_list[1::2]
    return new_list
a = user_list(['a','b','c','d','e','f','g','h','i',])
print(a)

 

  #6、写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
#dic = {"k1": "v1v1", "k2": [11,22,33,44]}
#PS:字典中的value只能是字符串或列表
def user_dic(in_dic):
    d = {}
    if not isinstance(in_dic,dict):
        print('%s is not dic.' % in_dic)
    else:
        for key in in_dic:
            if len(in_dic[key]) > 2:
                d[key] = in_dic[key][0:2]
                # val_dic = in_dic[key]
                # res_dic = val_dic[0:2]
    return d
# a = user_dic({'hello':['zhaoliying','liying','wangxiaochen']})
a = user_dic({'hello':'zhaoliying'})
print(a)

 

##########函数对象、函数嵌套、名称空间与作用域、装饰器##########

一、函数对象

  函数是第一类对象,即函数可以当做数据传递

    #可以被引用

    #可以当做参数传递

    #返回值可以是函数

    #可以当做容器类型的元素

  利用这个特性,可以优雅的取代多分支的if

def foo():
    print('From foo')
def bar():
    print('From bar')

dic = {
    'foo' : foo,
    'bar' : bar,
}

while True:
    choice = input('Input your choice:>').strip()
    if choice in dic:
        dic[choice]()

 

二、函数嵌套

  函数嵌套调用

  函数的嵌套定义

三、名称空间与作用域

  什么是名称空间?

    名称空间:存放名字x与1绑定关系的地方

  名称空间的加载顺序

    python test.py

    #python解释器先启动,首先加载:内置名称空间

    #执行test.py文件,加载全局名称空间

    #执行文件的过程中,如果调用函数,则临时产生局部名称空间

  名字的查找顺序

    局部名称空间--->全局名称空间--->内置名称空间

    #在全局无法查看局部的,在局部可以查看全局的

   

四、作用域

  作用域即范围,

    ---全局范围:全局存活,全局有效

    ---局部范围:临时存活,局部有效

  作用域关系在函数定义阶段就已经固定,与函数调用位置无关

  

五、闭包函数

  #闭包函数包含对外部作用域而非全局作用域的引用

  闭包的意义与应用

    闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

    应用领域: 延迟计算

 

六、装饰器

  为何要用装饰器?

    开放封闭原则:对修改封闭,对扩展开放

  装饰器的原则:

    不修改被装饰对象的源代码

    不修改被装饰对象的调用方式

  装饰器的目的:

    在遵循1和2的前提下,为被装饰对象添加上新功能

    #无参装饰器

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print('from foo')
foo()

 

    有参装饰器:

def auth(driver='file'):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == 'file':
                if name == 'egon' and pwd == '123':
                    print('login successful')
                    res=func(*args,**kwargs)
                    return res
            elif driver == 'ldap':
                print('ldap')
        return wrapper
    return auth2

@auth(driver='file')
def foo(name):
    print(name)

foo('egon')

 

posted @ 2017-12-19 23:25  LinuxPark  阅读(236)  评论(0编辑  收藏  举报