第三章:Python文件其他操作+函数入门

上一章主要讲了文件最基本的操作,这一章将要学习几个文件的函数:

文件

关于open 模式:

w 以写方式打开,
a 以追加模式打开 (从 EOF 开始, 必要时创建新文件)
r+ 以读写模式打开
w+ 以读写模式打开 (参见 w )
a+ 以读写模式打开 (参见 a )
rb 以二进制读模式打开
wb 以二进制写模式打开 (参见 w )
ab 以二进制追加模式打开 (参见 a )
rb+ 以二进制读写模式打开 (参见 r+ )
wb+ 以二进制读写模式打开 (参见 w+ )
ab+ 以二进制读写模式打开 (参见 a+ )

基本读文件:

# f=open('a.txt','r',encoding='utf-8')
# print(f.read(3))  #读前3个字符
#
# f=open('a.txt','rb')
# print(f.read(6).decode('utf-8'))#如果以utf-8的编码对str进行解码得到的结果,将无法还原原来的字符串内容
# print(f.read(3).decode('utf-8'))
# print(f.read(3)) #以rb模式打开,读取的是类似于2进制的内容
# f.closed 

Python文件操作常用函数:

1、seek

seek():移动文件读取指针到指定位置

seek()的三种模式:

    (1)f.seek(p,0)  移动当文件第p个字节处,绝对位置

    (2)f.seek(p,1)  移动到相对于当前位置之后的p个字节

    (3)f.seek(p,2)  移动到相对文章尾之后的p个字节

2、tell

tell():返回文件读取指针的位置 

# f=open('a.txt','rb')
# print(f.read(3))  #以二进制文件读取
# print(f.tell())   #文件的
# f.seek(3,0)  #移动文件读取指针到3个字节位置
# print(f.tell())  #返回文件读取指针的位置
# print(f.read(3).decode('utf-8'))
# b'123'
# 3
# 3
# 456
# f=open('a.txt','rb')
# print(f.read(3))
# print(f.tell())
# f.seek(3,1)   移动到相对于当前位置之后的3个字节
# print(f.tell())
# print(f.read().decode('utf-8'))
# b'123'
# 3
# 6
#
# 654321
#
# f=open('a.txt','rb')
# f.seek(0,2)
# print(f.tell())
# print(f.read())
# 14
# b''  #什么都没有读取到数据,指针说明已经在最后

练习:

下面来使用PY3写一个类似于命令tail -f /tailf  的功能,可以实时的观察文件的数据变化:

使用方法python3 tail.py -f access.log 

#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)
        else:
            time.sleep(0.2)
#acess.log

使用下面代码测试:

# with open('acess.log','a') as f:
#     f.write('1111\n')

 

函数

 

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。 

定义一个函数: 

你可以定义一个由自己想要功能的函数,以下是简单的规则: 

1、函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。 

2、任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。 

3、函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。 

4、函数内容以冒号起始,并且缩进。 

5、return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。 

函数的使用:
1 先定义
2 再调用

#函数的定义与变量的定义类似,没有事先定义变量,而直接引用变量,会报错
#没有事先定义函数,而直接调用,就相当于在引用一个不存在的变量名

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

 语法:

def functionname( parameters ):
   "函数_文档字符串"
   function_suite
   return [expression]

默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。

函数调用 

定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。

如下实例调用了printme()函数:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
# 定义函数
def printme( str ):
   "打印任何传入的字符串"
   print str;
   return;
 
# 调用函数
printme("我要调用用户自定义函数!");
printme("再次调用同一函数");

函数参数(传参)

#形参:在定义函数时,括号内的参数成为形参
#特点:形参就是变量名

# def foo(x,y): #x=1,y=2
# print(x)
# print(y)  

#实参:在调用函数时,括号内的参数成为实参
#特点:实参就是变量值

# foo(1,2)  

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

参数的分类

#位置参数:按照从左到右的顺序依次定义的参数
  1、位置形参:必须被传值,并且多一个不行,少一个也不行
  2、位置实参:与形参按照位置一一对应

# def foo(x,y):
#     print(x)
#     print(y)
#
# foo('egon',1,2)

#关键字实参:指的是按照name=value的形式,指名道姓地给name传值

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

关键字实参需要注意的问题是:

  1、问题一:语法规定位置实参必须在关键字实参的前面

foo('egon',sex='male',age=18)

  2、问题二:一定不要对同一个形参传多次值

foo('egon',sex='male',age=18,name='egon1')

默认形参:在定义阶段,就已经为形参赋值,意味在调用阶段可以不用传值

# def foo(x,y=1111111):
#     print(x)
#     print(y) 

默认参数:需要注意的问题
  1、问题一:默认参数必须放在位置参数之后

# def foo(y=1,x):  ##语法错误,×
# print(x,y)

  2、问题二:默认参数只在定义阶段赋值一次,而且仅一次

# x=100
# def foo(a,b=x):
# print(a,b)  
#
# x=111111111111111111111111111111
# foo('egon')  ###print后b输出的值不变:一直是100.

  3、问题三:默认参数的值应该定义成不可变类型

# def foo(a,b=100):
#     print(a,b)

函数的返回值

大前提:函数的返回值没有类型限制:int、list、set都可以返回。

  1、没有return:返回None,等同于return None

  2、return 一个值:返回该值

  3、return val1,val2,val3:返回(val1,val2,val3)  返回多个值。

def func(x,y):
    if x > y:
        return  x
    else:
        return  y
print(func(1,2))

 

#函数是第一类的对象:指的是函数可以被当做数据传递

def foo():
    print('from foo')
#1 被赋值
# f=foo   #被赋值的时候是函数名,不是函数体
# print(f)
# f()

#2 可以当做参数传入
# def wrapper(func):
#     # print(func)
#     func()
# wrapper(foo)

#3 可以当做函数的返回
def wrapper(func):
    return func
# res=wrapper(foo)
# print(res)

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

# cmd_dic={
#     'func':foo
# }
#
# print(cmd_dic)
#
# cmd_dic['func']()

 

可变长参数:

针对实参在定义时长度不固定的情况,应该从形参的角度找到可以接收可变长实参的方案,这就是可变长参数(形参)
        而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参也应该有两种解决方案,分别是*args,**kwargs

注意:

1、可变长参数指的是实参的个数(不固定)多了

2、实参无非位置实参和关键字实参两种

3、形参必须要两种机制来分别处理按照位置定义的实参溢出的情况:*

4、跟按照关键字定义的实参溢出的情况:**

==>位置实参:

def func(x,y,*args):  # args=(4,5,6,7)
    print(x)
    print(y)
    print(args)
func(1,2,3,4,5,6,7)
打印的值:
 
结论:func多出的参数就会给'*'处理,存储成元祖的形式赋值给args
def func(x,y,*args):  #把参数去掉就会
    print(x)
    print(y)
    print(args)
func(1,2)
 
输出一个空元祖。
*args的扩展用法:
def func(x,y,*args):  # *args=*(3,4,5,6,7)
    print(x)
    print(y)
    print(args)
func(1,2,*(3,4,5,6,7))  #等价于func(1,2,3,4,5,6,7)
def func(x,y,):
    print(x)
    print(y)
func(1,*(2,))  #等价于func(1,2)
 

def func(x,y=1,*args): #问题:有默认参数y ,这样使得y没有意义。
    print(x)
    print(y)
    print(args)
func('sheng',101,2,3,4,5,6)
 
func('sheng',101,2,3,4,5,y=2)  #报错,同一个参数传2次值
View Code

==>关键字实参:

def func(x,y,**kwargs):
    print(x)
    print(y)
    print(kwargs)
func(x=1,y=2,c=3,d=4,e=5,f=6) 
 
结论:func多出的参数就会给'**'处理,存储成字典的形式赋值给kwargs
def func(x,y):
    print(x)
    print(y)

func(**{'x':1,'y':3})  #==》func(x=1,y=3)  #实参也可以有**的方式传参
 
注意:
def foo(*args,x):
    print(x)
    print(args)
foo(1,2,3,4,5,)  #无法为x传值,都传给了args
应该修改成:
def foo(*args,x):
    print(x)
    print(args)
foo(1,2,3,4,5,x=33)  #无法为x传值,都传给了args
 
def foo(x,*args,**kwargs):  #args=(1,2,3,4,5),kwargs={'a':22,'b':33} #正常的定义方式
    print(x)
    print(args)
    print(kwargs)
foo(1,2,3,4,5,a=22,b=33)
这两定义方式*args,**kwargs干什么使用:
def register(name,age,sex='female'):
    print(name)
    print(age)
    print(sex)
def foo(*args,**kwargs):  #args=(1,2,3,4,5),kwargs={'a':22,'b':33}
    register(*args,**kwargs)   
foo('sheng',age=28)
View Code

 

posted @ 2017-07-19 16:45  ShengLeQi  阅读(149)  评论(0)    收藏  举报