文件操作及函数

文件处理

f = open(‘a.txt’,’r’)  
f.read()

open是在打开一个文件,是在哪里发起的请求?是在.py文件里面发起的,是自己写的应用程序,应用程序能直接操作硬件吗?所以这一步是在向操作系统发起一个请求,是不是要打开一个文件

打开一个文件,最后赋值给f,这个f被应用程序的内存拿着,其实就是python变量的赋值操作,但是不仅仅拿到了f,操作系统还打开了一个文件对应着,用户可以直接拿着f,用f.read()执行读操作,这是系统调用,向操作系统发起了请求,正好对应操作系统打开的文件,操作系统接到read指令后,会到硬盘上读内容,然后返回给程序

字符编码

    什么是字符编码
        把人类的字符翻译成计算机能认识的数字
    什么是字符编码表
        就是一张字符与数字对应关系的表
        Ascii
        Gbk
        Utf-8
        Unicode

    Unicode-->encode(‘utf-8’)-->bytes
    Bytes---->decode(‘utf-8’)---->unicode

内存用的都是unicode,为的是保证速度,硬盘用utf-8,用gbk都行,为的是存储容量越小越好

原则:
    字符以什么格式编码的就要以什么格式解码

补充:

写程序和编辑普通文件没有什么区别,最后保存在硬盘上,运行是交给cpu运行,
硬盘如何让cpu去运行呢?首先要把文件中的内容整体先加载到内存中,再谈执行的问题
那么硬盘中以utf-8编码的往内存中里面走,应该是解码成unicode.

python3中的字符串分为两种
x='egon' 存成unicode
y=x.encode('utf-8') 存成bytes
----------------------------------
python2中的字符串也分为两种
x = u'egon' 与python3中的字符串一样
y = 'alex' 与python3的bytes一样
#r文本模式的读,在文件不存在时,不会创建新文件
f=open('a.txt','r',encoding='utf-8')
print(f.read())
print(f.readline())
print(f.readlines()) f.close()
#rb模式即直接从硬盘中读取bytes f=open('a.txt','rb') # 因为是直接从硬盘中读取的二进制,所以不需要encoding print(f.read()) #b'xe4xbdxa0xe5xa5xbdxe5x95x8aalex' print(f.read().decode('utf-8')) #你好啊

#wb模式
f=open('a.txt','wb')
#f.write('你好啊') #会报错
f.write('你好啊'.encode('utf-8'))
# Python3的字符串是unicode类型,unicode转为bytes需要encode

#python3 copy.py a.jpg  b.jpg     拷贝文件,文本文件(字符编码),非文本文件(编码有问题,所以只能采取二进制模式拷贝文件)。采用二进制,无论什么格式,都不会乱码
---------------------------------------------
import sys

#python copy.py source.file target.file
# print(sys.argv)
# sys.exit()

if len(sys.argv) < 3:  # 需要三个参数
    print('Usage:python3 copy.py source.file target.file')
    sys.exit()

#r'c:UsersAdministratorPycharmProjectspyhton18'
#python copy.py C:source.file D:	arget.file
#处理windows路径的方式
with open(r'%s' % sys.argv[1],'rb') as read_f,
        open(r'%s' % sys.argv[2],'wb') as write_f:
    for line in read_f:
        write_f.write(line)

文件其他操作

#w文本模式的写,文件存在则清空,不存在则创建
f=open('a.txt','w',encoding='utf-8')
f.write('你好
')
f.writelines(['1111
','222
'])
#a文本模式的追加,文件存在,光标跳到文件末尾,文件不存在则创建
f=open(‘b.txt’,'a',encoding='utf-8')
print(f.writable())  #True
print(f.readable()) #Falese

打开文件并不是应用程序自己的事情,打开文件后,我们拿到了变量名f,对应着一个值,这个f是应用程序拿着,操作系统还拿着打开的文件,如果要回收,应该是两个都要回收掉

f=open('a.txt','wb')
f.write('你好啊'.encode('utf-8'))

print(f) # <_io.BufferedWriter name='a.txt'>
f.close() # 向操作系统发起请求,关闭掉打开的文件,操作系统回收掉打开的文件,
print(f) #<_io.BufferedWriter name='a.txt'>,虽然关掉了文件,但是f是应用程序级别定义的变量,这个变量是在这个变量f对应的值没有引用了才会被回收掉
print(f.read) # 方法依然还有
print(f.readable) # 方法依然还有
f.read() # 不能运行,向操作系统发请求,操作系统已经关掉了这个文件,所以会报io出错

#del f # 回收掉了应用程序级别的
# a.txt 
你好啊1
你好啊2
你好啊3

f=open('a.txt','r',encoding='utf-8')
print(f.read(3))    #文件打开方式为文本模式时,代表读取3个字符
#你好啊
# a.txt 
你hello好啊1
你好啊2
你好啊3

f=open('a.txt','r',encoding='utf-8')
print(f.read(3))    #文件打开方式为文本模式时,代表读取3个字符
#你he
# a.txt 
你hello好啊1
你好啊2
你好啊3

f=open('a.txt','rb')
print(f.read(3))    #文件打开方式为二进制模式时,代表读取3个字节

#b'xe4xbdxao'

print(f.read(3).decode('utf-8'))
# 你      三个字节,unicode是三个字节存一个中文 
print(f.read(2))  # b'xe4xbd'
print(f.read(2).decode('utf-8'))  #报错  2个字节无法解出一个中文

一.read(3):

    1.文件打开方式为文本模式时,代表读取3个字符        # 只有read的文本模式可以读字符,除此以外全是以字节为单位,不管文件打开模式是什么模式,都是以字节为单位

    2.文件打开方式为b模式时,代表读取3个字节 

#a.txt
你好啊alex

f=open('a.txt','r',encoding='utf-8')
print(f.read())
f.seek(3)
print(f.tell())
print(f.read())

# 你好啊alex
# 3
# 好啊alex

f=open('a.txt','r',encoding='utf-8')
print(f.read(3))
print(f.tell()) #以字节为单位显示
print(f.read(1))
f.seek(6)
print(f.read(1))
# 你好啊
# 9
# a
# 啊

二.其余文件内光标移动都是以字节为单位,如seek,tell,truncate

    1.seek有三种移动方式,0.1.2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

    f.seek(6,0)    f.seek(6,1)   f.seek(6,2)    # 0,1,2  指定的参照物不一样

    0  默认参照物为文件开头,

    1 以当前光标所在的位置为参照物    

    2 从结尾位置为参照物

    f=open('a.txt','rb')        1和2必须在b模式下进行

    f.read(3)  read了三个字符,正好是三个中文字符,9个字节  f.seek(2,1)  当前光标是在第9个字节,在第9个字节往后seek了2个字节,所以光标现在在第11个字节

f=open('a.txt','rb')
print(f.read(3))   # 读了3个字节
print(f.tell())   # 3
f.seek(3,0)
print(f.tell())  # 3
print(f.read(1))  #读的是第4个字节

f=open('a.txt','rb')
print(f.read(3)) # b'xe4xbdxa0'
print(f.tell()) # 3
f.seek(3,1) # 基于当前光标往后移动了3个字节
print(f.tell()) # 6


# a.txt
你好啊alex

f=open('a.txt','rb')
f.seek(0,2) #相对于文件末尾seek 0个位置
print(f.tell()) # 13,文件的结尾
f.seek(-1,2) #向左切一个字节
print(f.read()) # b'x'

    2.truncate(没有用)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为会直接清空文件,所以truncate要在r+或a或a+等模式下测试

with open('a.txt','r+',encoding='utf-8') as f:
    f.truncate(9)  #  从文件开头开始截9个字节

#你好啊

模拟linux的tail 命令

#python3 tail.py -f access.log
            0     1    2
import time
import sys

with open(r'%s' % sys.argv[2],'rb') as f:
    f.seek(0,2)  # 光标直接切到文件末尾,等待新内容
 
    while True:
        line = f.readline()
        if line:    #如果有新内容出现
            print(line.decode('utf-8'),end='')
        else:
            time.sleep(0.2)
   
追加    # access.log
with open('access.log','a') as f:
    f.write('1111
')

函数

问题:
     1.复杂度增大
     2.组织结构不清晰
     3.可读性差
     4.代码冗余
     5.可扩展性差

如何解决问题:
     1.工具就是具备某一种功能的物件,就是程序中函数的概念
     2.事先准备工具的过程称为函数的定义
     3.遇到特定的场景拿来就用称为函数的调用

分类:
     1.内置函数(解释器自带的)
     2.自定义函数
 
1.先定义
      函数的定义与变量的定义类似,没有事先定义变量,而直接引用变量
      会报错,没有事先定义函数,而直接调用,就相当于在引用一个不存在的变量名

def foo():
    print('from foo')

2.再调用

foo()  #先根据foo这个名字找到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()       # 不会报错

# from foo
# from bar

函数定义语法

def 函数名(arg1,arg2,arg3):
    '''注释'''
    函数体
    return  返回值

函数名一般是动词

定义的三种形式

无参
    应用场景仅仅只是执行一些操作,比如与用户交互,打印
有参
    需要根据外部代码传进来的参数,才能执行相应的逻辑

def my_max(x,y):
    if x > y:
        print(x)
    else:
        print(y)

my_max(1,2)
# 2


def my_max(x,y):
    if x > y:
        print(x)
    else:
        print(y)

res=my_max(1,2)

print(res)

#2

#None

def foo():

    print('-----')

    return 123     # 函数内可以有多个return,但只能执行一次,整个函数就结束掉,并且会把return后的值作为函数执行的结果返回

    print('-----')

foo()

#-----

空函数
    设计代码结构

def select(sql):
'''select function'''
print(sql)
#sql=['select','*','from','mysql.user;']
def insert(sql):
'''insert function'''
pass

def update(sql):
'''update function'''
pass

def delete(sql):
'''delete function'''
pass

# select * from mysql.user;

def main():
    while True:
        sql=input('>>: ').strip()
        if not sql:continue
        cmd_info=sql.split()
        cmd=cmd_info[0]


        if cmd == 'select':
            select(cmd_info)

        elif:

       .....
main()

文件补充: 

#一行一行打印,同一时间,内存中只有一行内容
with open('a.txt','r',encoding='utf-8') as f:
    for line in f:
    print(line)
def func():
    print('from func')
    return [1,2,3],'a',1,{'a':3}
res = func()
print(res)

return的返回值没有类型限制
    没有return,返回None,等同于return None
    return 一个值,返回该值
    return val1,val2,val3;返回(val1,val2,val3)

什么时候该有返回值?

 调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
 通常有参函数需要有返回值,输入参数,经过计算,得到一个最终结果
 
什么时候不需要有返回值?
 调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果
 则无需要有返回值

函数调用的三种形式

def my_max(x,y):
    if x > y:
        return x
    else:
        return y
  
res = my_max(1,2)   #语句形式
res1 = my_max(1,2)*10   #表达式形式
res2 = my_max(my_max(1,2),3)  #函数调用可以当作另外一个函数的参数
def func():
    print('from func')
    return [1,2,3],'a',1,{'a':3}

res = func()
print(res)

函数参数:

#在定义函数时,括号内的参数称为形参,不占内存空间
def
foo(x,y): #x,y是形参, x=1,y=2 形参就是变量名 print(x) print(y) #在调用函数时,括号内的参数称为实参,真正占内存空间的 foo(1,2) #1,2是实参 实参就是变量值

#在调用阶段,实参(变量值)才会绑定形参(变量名),调用结束后,解除绑定

参数的分类:

位置参数:按照从左到右的顺序依次定义的参数

    1.位置形参:必选参数,多一个不行,少一个不行

    2.位置实参:与形参按照位置一一对应

def foo(name,age):
    print(name)
    print(age)

foo('tom',1)

关键字参数

def foo(name,age):
    print(name)
    print(age)

foo(age=1,name='tom')

默认形参

x=100
def foo(a,b=x):   #定义阶段
    print(a,b)
 
x=0
foo('egon')

# egon 100

默认参数只在定义阶段赋值一次,而且仅一次

默认参数的值应该定义成不可变类型

可变长参数:实参的个数不固定

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

foo(1,2,3,4,5,6,7)
def foo(x,y,**kwargs):
    print(x)
    print(y)
    print(kwargs)
foo(x=1,y=2,z=3,a=1,b=2)
#装饰器的前身
import
time def register(name,age,sex='male'): print(name) print(age) print(sex) time.sleep(3)
#统计register函数运行了多长时间,前提是不能更改register内部的源代码
def wrapper(*args,**kwargs): start_time=time.time() register(*args, **kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time))
wrapper(
'egon',age=18) #但是函数的调用方式变了,由调用register(),改为调用wrapper(),目前只能到这里,到装饰器时再把调用方式改为register()

 命名关键字参数:在*后面定义的形参称为命名关键字参数,

必须是以关键字实参的形式传值

def foo(name,age,*,sex):
    print(name)
    print(age)
    print(sex)

foo('egon',18,sex='male')
def foo(name,age,*,sex='male',group):
    print(name)
    print(age)
    print(sex)
    print(group)
 
foo('egon',18,group='group1',sex='male')
def foo(name,age,*args,sex='male',group):
    print(name)
    print(age)
    print(args)
    print(sex)
    print(group)
  
foo('egon',18,19,20,300,group='group1') 

# egon
# 18
# (19, 20, 300)
# male
# group1

顺序很重要,但是没有全放在一起的场景

def foo(name,age=18,*args,sex='male',group,**kwargs):
    pass

函数对象

函数是第一类的对象,指的是函数可以被当作数据传递

1.被赋值

def foo():
    print('from foo')
 
f=foo
print(f)    # 就是foo那个函数
f()         # 相当于执行foo()

2.可以当作参数传入

def wrapper(func):
    print(func)     #打印函数foo的内存地址
    func()          #运行foo函数
 
wrapper(foo)     # foo对应的内存地址传给func

3.可以当作函数的返回值

def wrapper(func):
    return func

res=wrapper(foo)
print(res)        #返回foo的内存地址

4.可以当作容器类型的元素

cmd_dic={
'func':foo   #返回的是字典,{'func': <function foo at 0x00000250CA033E18>}
}
print(cmd_dic)

cmd_dic['func']()  #运行foo函数
def select(sql):
    '''select function'''
    print('select--->',sql)

def insert(sql):
    '''insert function'''
    print('insert--->',sql)

def update(sql):
    '''update function'''
    print('update--->',sql)

def delete(sql):
    '''delete function'''
    print('delete--->',sql)

cmd_dic = {
    'insert':insert,
    'update': update,
    'delete': delete,
    'select': select
}

def main():
    while True:
        sql=input('>>: ').strip()
        if not sql:continue
        cmd_info=sql.split()
        cmd=cmd_info[0]

        if cmd in cmd_dic:
            cmd_dic[cmd](cmd_info)
        else:
            print('cmd not exists')


main()

匿名函数lambda

待补充

内建函数

待补充

函数的递归调用

待补充

二分法

待补充

文件补充

with open('a.txt','r',encoding='utf-8') as f:
    l = f.readlines()
    for line in l:
        print(line,end='')

一次性把文件全部都到内存里,若文件很大,会撑爆内存

with open('a.txt','r',encoding='utf-8') as f:
    for line in f:
        print(line,end='')

同一时间,内存里只有一行内容

原文地址:https://www.cnblogs.com/Ryans-World/p/7218790.html