Python中的文件对象.函数.模块基础

文件对象

处理文件的三个步骤:打开、读写、关闭。

文件打开方法
  • open内建函数
    • 作为打开文件之门的“钥匙”,内建函数open() 提供了初始化输入/输出(I/O)操作的通用接口
    • 成功打开文件后时候会返回一个文件对象,否则引发一个错误
    • 基本语法:
    file_object = open(file_name, mode='r', buffering=-1)
  • 文件对象访问模式
文件模式 操作
r 以读方式打开(文件不存在则报错)
w 以写方式打开(文件存在则清空,不存在则创建)
a 以追加模式打开(必要时创建新文件)
r+ 以读写模式打开(参见r)
w+ 以读写模式打开(参见w)
a+ 以读写模式打开(参见a)
b 以二进制模式打开
  • 文件读取
[root@room8pc16 ]# cp /etc/passwd /tmp/mima
>>> f = open('/tmp/mima')   # 默认以r方式打开
>>> data = f.read()         # 默认read读取全部数据
>>> print(data)

>>> data = f.read()         # 因为文件指针已经到文件结尾,再读数据将是空
>>> print(data)

>>> data
''
>>> f.close()
  • 重新打开文件
>>> f = open('/tmp/mima')
>>> f.read(4)      # 读取4字节
'root'
>>> f.read(4)
':x:0'
>>> f.readline()   # 读取到遇到的第一个\n
>>> f.readlines()  # 把文件的第一行作为列表项,保存到列表中
>>> f.close()

最常用的、读取文本文件的方式是for循环遍历:

>>> f = open('/tmp/mima')
>>> for line in f:
...     print(line, end='')
>>> f.close()
  • write方法
  1. write()内建方法功能与read()和readline()相反。它把含有文本数据或二进制数据块的字符串写入到文件中去
  2. 写入文件时,不会自动添加行结束标志,需要程序员手工输入
    >>> fobj.write('Hello World!\n')
    13
  • writelines方法
  1. 和readlines()一样,writelines()方法是针对列表的操
  2. 它接受一个字符串列表作为参数,将它们写入文件
  3. 行结束符并不会被自动加入,所以如果需要的话,必
    须在调用writelines()前给每行结尾加上行结束符
    >>> fobj.writelines(['Hello World!\n', 'python programing\n'])
  • 写文件
>>> f = open('/tmp/mima', 'w')        # 文件不存在则创建,存在会清空
>>> f.write('hello world!\n')
13           # 返回写入到文件的字节数
>>> f.writelines(['2nd line.\n', '3rd line.\n'])
[root@room9pc01 ~]# cat /tmp/mima     # 此时文件仍然为空的
>>> f.flush()                         # 立即将数据从缓存同步到磁盘
[root@room9pc01 ~]# cat /tmp/mima
hello world!
2nd line.
3rd line.
>>> f.write('end\n')
4
>>> f.flush()
>>> f.write('kjlkjl\n')
7
>>> f.close()                         # 关闭文件时,数据也会写入磁盘
  • 处理非文本文件,与文本文件大体相似,只不过在打开文件时,需要加上b
>>> f = open('/tmp/ls')
>>> f.read(10)   # 报错.因为打开时默认以UTF-8编码打开,但是ls不是文本文件,读取时,Python试图把读出来的10个字节显示为UTF-8字符
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/codecs.py", line 321, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 24: invalid continuation byte
>>> f.close()
>>> f = open('/tmp/ls', 'rb')  # 以bytes类型打开
>>> f.read(10)       
b'\x7fELF\x02\x01\x01\x00\x00\x00'

# 文本文件也能以bytes方式打开
>>> f = open('/tmp/mima', 'rb')
>>> f.read()
b'hello world!\n2nd line.\n3rd line.\nend\nkjlkjl\n'
>>> f.close()
with子句
  • with语句是用来简化代码的
  • 在将打开文件的操作放在with语句中,代码块结束后,文件将自动关闭
>>>	with	open('foo.py')	as	f:
...		data = f.readlines()
...
>>>	f.closed
True
  • 文件打开后,如果不关闭,也可能没有问题,当程序结束时.文件自动关闭,但是关闭文件是很好的习惯。
  • 如果使用with语句打开文件,当with语句结束时,文件自动关闭。
>>> with open('/tmp/mima') as f:
...     f.readline()
...     f.readline()
... 
'hello world!\n'
'2nd line.\n'
>>> f.readline()     # 文件已经关闭,无法再读取数据
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
文件内移动
  • seek(offset[, whence]):移动文件指针到不同的位
    – offset是相对于某个位置的偏移量
    – whence的值,0表示文件开头,1表示当前位置,2表示文件的结尾
  • tell():返回当前文件指针的位置
  • 移动文件指针:seek(x, y)。y可以取值0,1,2,分别表示文件开头、当前位置和结尾。x是偏移量。
>>> f = open('/tmp/mima')
>>> f.tell()   # 显示当前位置,永远从开头算偏移量
0
>>> f.seek(5, 0)
5
>>> f.read(1)
' '
>>> f.close()

>>> f = open('/tmp/mima')
>>> f.read()   # 读取全部内容
>>> f.read()   # 再读就没有数据了
''
>>> f.seek(0, 0)   # 回到文件开头
0
>>> f.read()   # 再次读取文件内容
>>> f.close()  # 关闭文件


>>> f = open('/tmp/mima', 'rb')
>>> f.seek(-5, 2)   # 指针移动到文件结尾前5个字节处
32
>>> f.read()
b'\nend\n'
#以下写法,可以工作,但是不好,如果源文件很大,数据读取出来赋值给打data
#将会消耗大量内存
with open('/bin/ls', 'rb') as f1:
    data = f1.read()
with open('/tmp/list', 'wb') as f2:
    f2.write(data)

scr_fobj = open(scr_fname,'rb')
dst_fobj = open(dst_fname, 'wb')

while True:
    data = scr_fobj.read(4096)      # 每次最多读取4096字节
    #if data == b'':
    #if len(data) == 0:             #leg(b'')  -> 0
    if not data:                    #data值为b'',表示False
        break
    else:
        dst_fobj.write(data)
    
scr_fobj.close()
dst_fobj.close()

函数基本操作

函数基本概念
  • 函数是对程序逻辑进行结构化或过程化的一种编程方
  • 将整块代码巧妙地隔离成易于管理的小块
  • 把重复代码放到函数中而不是进行大量的拷贝,这样既能节省空间,也有助于保持一致性
  • 通常函数都是用于实现某一种功能
创建函数
  • 函数是用def语句来创建的,语法如下:
def function_name(arguments):
     "function_documentation_string"
function_body_suite
  • 标题行由def关键字,函数的名字,以及参数的集合(如果有的话)组成
  • def子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必需的函数体
调用函数
  • 同大多数语言相同,python用一对圆括号调用函数
  • 如果没有加圆括号,只是对函数的引用
>>>	def foo():
...		print('hello')
...
>>>	foo()
hello
>>>	foo
<function	foo	at	0x7ff2328967d0>
例子:
def fib_func():
    #函数定义时,不会执行函数体内的代码
    fib = [0,1]

    n = int(input('长度: '))
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])

    print(fib)

fib_func()             # 函数调用时,将会执行函数体内的代码
fib_func()
fib_func()
函数的返回值
  • 多数情况下,函数并不直接输出数据,而是向调用者返回值
  • 函数的返回值使用return关键字
  • 没有return的话,函数默认返回None
>>>	def foo():
...		res	= 3 + 4
>>>	i =	foo()
>>>	print	i
None
例子:
def fib_func():
    #函数定义时,不会执行函数体内的代码
    fib = [0,1]
    n = int(input('长度: '))
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])
    return fib  # 函数的运行结果.用关键字return返回
a = fib_func()
print(a)

函数参数

定义参数
  • 形式参数
    函数定义时,紧跟在函数名后(圆括号内)的参数被称为形式参数,简称形参。由于它不是实际存在变量,所以又称虚拟变量
def fib_func(n):  # 函数的参数,形参
    fib = [0,1]
    for i in range(n - 2):
        fib.append(fib[-1] + fib[-2])
    return fib    # 函数的运行结果.用关键字return返回
for i in range(2, 10):
    print(fib_func(i))
  • 实际参数
    在主调函数中调用一个函数时,函数名后面括弧中的参数(可以是一个表达式)称为“实际参数”,简称实参
传递参数
  • 调用函数时,实参的个数需要与形参个数一致
  • 实参将依次传递给形参
>>>	def foo(x,	y):
...		print('x=%d,y=%d' % (x,y))
>>>	foo()
Traceback (most	recent	call	last):
File	"<stdin>",	line	1,	in	<module>
TypeError: foo() takes exactly 2 arguments (0 given)
>>>	foo(3)
Traceback (most recent call last):
File "<stdin>",	line 1, in <module>
TypeError: foo() takes exactly 2 arguments (1 given)
>>>	foo(3, 4)
x=3, y=4
位置参数
  • 与shell脚本类似,程序名以及参数都以位置参数的方式传递给python程序
  • 使用sys模块的argv列表接收
[root@room9pc01 day03]# cat 3.py 
# Python的位置变量保存在sys.argv列表中,即,argv是sys模块的一个列表
import sys
print(sys.argv)
[root@room9pc01 day03]# python3 3.py 
['3.py']
[root@room9pc01 day03]# python3 3.py hao 
['3.py', 'hao']
[root@room9pc01 day03]# python3 3.py hao 123
['3.py', 'hao', '123']

import sys
def copy(scr_fname, dst_fname):
    scr_fobj = open(scr_fname,'rb')
    dst_fobj = open(dst_fname, 'wb')
    while True:
        data = scr_fobj.read(4096) # 每次最多读取4096字节
        #if data == b'':
        #if len(data) == 0:   #leg(b'')  -> 0
        if not data:       #data值为b'',表示False
            break
        else:
            dst_fobj.write(data)

    scr_fobj.close()
    dst_fobj.close()

copy(sys.argv[1], sys.argv[2])
默认参数
  • 默认参数就是声明了默认值的参数
  • 因为给参数赋予了默认值,所以在函数调用时,不向该参数传入值也是允许的
python
def pstar(n=30):
    print('*' * n)

pstar(10)       # 传参,使用n=10
pstar(50)       # 传参,使用n=50
pstar(60)
pstar()         # 传参,使用默认n=30

模块基础

模块实际上就是一个以.py结尾的文件,去除.py之后前面的文件名

模块基本概念
  • 模块是从逻辑上组织python代码的形式
  • 当代码量变得相当大的时候,最好把代码分成一些有组织的代码段,前提是保证它们的彼此交互
  • 这些代码片段相互间有一定的联系,可能是一个包含数据成员和方法的类,也可能是一组相关但彼此独立的操作函数
创建模块
  • 模块物理层面上组织模块的方法是文件,每一个以.py作为结尾的python文件都是一个模块
  • 模块名称切记不要与系统中已存在的模块重名
  • 模块文件名字去掉后面的扩展名(.py)即为模块名
导入模块(import)
  • 使用import导入模块
  • 模块属性通过“模块名.属性”的方法调用
  • 如果仅需要模块中的某些属性,也可以单独导入

导入模块的方法

  • import os :常用
  • from random import randint,choice:仅导入模块的某些功能
>>> from random import randint, choice
>>> randint(1, 10)
5
>>> choice('abd')
'a'
>>> random.randint(1, 10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined
  • import sys,time,getpass :不常用
  • import getpass as gp: 导入模块时,为其创建别名,不常用
>>> import getpass as gp
>>> gp.getpass()
Password:
  • 第一模块导入(import)时,模块中的代码将会执行(load)一遍;再次导入,代码就不再执行了。
模块导入的特殊属性
  • 每个模块都有一个内部变量叫_name_, _name_值有两种。当程序文件直接运行的时候,它的值是_main_,当它被别的程序导入时,值是模块名。
[root@room8pc16 day03]# cat foo.py
print(__name__)
[root@room8pc16 day03]# cat bar.py
import foo
[root@room8pc16 day03]# python3 foo.py
__main__
[root@room8pc16 day03]# python3 bar.py
foo

猜你喜欢

转载自blog.csdn.net/weixin_44965389/article/details/94569369
今日推荐