Python 基础部分-4
文件的基本操作
open()
用于文件处理
操作文件时,一般需要经历如下步骤:
- 打开文件
- 操作文件
- 关闭文件
基本操作文件方式
open(文件名/路径,模式,编码),默认模式为“只读”
f = open('test.log', "r") data = f.read() f.close() print(data) >>> testlog
打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。
打开文件的模式:
- r ,只读模式【默认】
f = open('test.log') data = f.read() f.close() print(data) >>> abc123
- w,只写模式【不可读;文件不存在则创建;文件存在则清空内容;】
f = open('test.log', 'w') data = f.write('defg123456') #以写方式覆盖文件 f.close() print(data) >>> 10 #写入10个字符
f = open('test.log', 'w') data = f.read() f.close() print(data) >>> data = f.read() io.UnsupportedOperation: not readable#只写方式不能读取文件内同
- x, 只写模式【不可读;文件不存在则创建;文件存在则报错】
f = open('test2.log', 'x')#文件不存在,创建一个新的文件 f.write("qwe456") f.close() f = open('test2.log', 'x') f.write("zxcv123456") f.close() >>> f = open('test2.log', 'x') FileExistsError: [Errno 17] File exists: 'test2.log'#文件已经存在,不能创建同名文件
- a, 追加模式【不可读;文件不存在则创建;文件存在则只追加内容;】
f = open('test2.log', 'a') data = f.write("9876543210") f.close() print(data) >>> 10 #写入10个字符
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】
先读取文档,在文档末尾追加写入,指针移到最后
f = open("test.log", 'r+', encoding = "utf-8") print(f.tell()) #显示指针位置,指针从开始向后读取 f.write("123456") data = f.read() print(data) print(f.tell()) #读取文件后指针位置 f.close() >>> 0 123456 6
- w+,写读【可读,可写】
先把文件内容清空,从开始向后读取文件;重新写入内容后,指针移到最后,读取文件。
f = open("test.log", 'w+', encoding = "utf-8") f.write("123456")#写入完成后,文档指针位置在文件末尾 f.seek(0)#设定指针在文档开始 data = f.read() print(data)
- x+ ,写读【可读,可写】
若文件存在,系统报错,建新文件,再写入内容后,指针移到最后,读取文件。
- a+, 写读【可读,可写】
文件打开同时,文档指针已经设定在最后, 写入文件后,指针留在文件的最后。
f = open("test.log", 'a+', encodig"utf-8") f.write("987654") print(f.tell()) #显示指针位置 f.seek(0) #设定指针为文档最开始 data = f.read() print(data) >>> 6 987654
r+ w+ x+ a+都以指针位置读取或写入数据。
"b"表示以字节(bytes)的方式操作
- rb 或 r+b
f = open('test2.log', 'wb') f.write(bytes("中国", encoding='utf-8')) f.close() f = open('test2.log', "rb") data = f.read() f.close() print(data) str_data = str(data, encoding='utf - 8') print(str_data) >>> b'\xe4\xb8\xad\xe5\x9b\xbd' 中国
- wb 或 w+b
f = open('test2.log', 'wb') str_data = "中国" bytes_data = bytes(str_data, encoding = 'utf-8')#指定写如的编码 f.write(bytes_data) f.close()
f = open('test2.log', 'wb') f.write("中国") f.close() >>> f.write("中国") TypeError: a bytes-like object is required, not 'str'
- xb 或 x+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型
普通打开方式
python内部将底层010101010的字节 转换成 字符串
二进制打开方式
python将读取将底层010101010的字节 再按照程序员设定的编码,转换成字符串。
f = open('test2.log', 'wb') f.write(bytes("中国", encoding='utf-8')) f.close() f = open('test2.log', "rb") data = f.read() f.close() print(data) str_data = str(data, encoding='utf - 8') print(str_data) >>> b'\xe4\xb8\xad\xe5\x9b\xbd' 中国
文件操作内部函数
f.flush()
主动把内容刷新到硬盘内
f = open("test.log", "r+", encoding="utf-8") f.write("123456789")#内容写入到内存中 f.flush()#把内容刷新到硬盘内 i = input(">>>")
f.readline()
仅读取一行内容
f1 = open("test.log", 'r+', encoding = 'utf-8') d = f1.realline() f.close() print(d)
f.tell()
显示指针位置
f.seek()
设定指针位置
f.trucate()
截取数据,仅保留指针前的数据
f = open("test.log", "r+", encoding = "utf-8") print(f.tell()) print(f.seek(6)) f.truncate() f1.close()
f.close()
关闭文件,把文件保存在硬盘中
使用for循环读取文件
f = open("xxx", "r")
for line in f: print(line)
with 循环打开文件
with open("xxx", 'r') as f: f.read() f = open("xxx", 'r') f.read() #不需要f.close()关闭文件
with支持同时打开两个文件,从源文件中逐行拷贝到目标文件中
with open("test.log", 'r') as obj1, open ("test2.log", 'w') as obj2: for line in obj1: obj2.write(line)
class file(object) def close(self): # real signature unknown; restored from __doc__ 关闭文件 """ close() -> None or (perhaps) an integer. Close the file. Sets data attribute .closed to True. A closed file cannot be used for further I/O operations. close() may be called more than once without error. Some kinds of file objects (for example, opened by popen()) may return an exit status upon closing. """ def fileno(self): # real signature unknown; restored from __doc__ 文件描述符 """ fileno() -> integer "file descriptor". This is needed for lower-level file interfaces, such os.read(). """ return 0 def flush(self): # real signature unknown; restored from __doc__ 刷新文件内部缓冲区 """ flush() -> None. Flush the internal I/O buffer. """ pass def isatty(self): # real signature unknown; restored from __doc__ 判断文件是否是同意tty设备 """ isatty() -> true or false. True if the file is connected to a tty device. """ return False def next(self): # real signature unknown; restored from __doc__ 获取下一行数据,不存在,则报错 """ x.next() -> the next value, or raise StopIteration """ pass def read(self, size=None): # real signature unknown; restored from __doc__ 读取指定字节数据 """ read([size]) -> read at most size bytes, returned as a string. If the size argument is negative or omitted, read until EOF is reached. Notice that when in non-blocking mode, less data than what was requested may be returned, even if no size parameter was given. """ pass def readinto(self): # real signature unknown; restored from __doc__ 读取到缓冲区,不要用,将被遗弃 """ readinto() -> Undocumented. Don't use this; it may go away. """ pass def readline(self, size=None): # real signature unknown; restored from __doc__ 仅读取一行数据 """ readline([size]) -> next line from the file, as a string. Retain newline. A non-negative size argument limits the maximum number of bytes to return (an incomplete line may be returned then). Return an empty string at EOF. """ pass def readlines(self, size=None): # real signature unknown; restored from __doc__ 读取所有数据,并根据换行保存值列表 """ readlines([size]) -> list of strings, each a line from the file. Call readline() repeatedly and return a list of the lines so read. The optional size argument, if given, is an approximate bound on the total number of bytes in the lines returned. """ return [] def seek(self, offset, whence=None): # real signature unknown; restored from __doc__ 指定文件中指针位置 """ seek(offset[, whence]) -> None. Move to new file position. Argument offset is a byte count. Optional argument whence defaults to (offset from start of file, offset should be >= 0); other values are 1 (move relative to current position, positive or negative), and 2 (move relative to end of file, usually negative, although many platforms allow seeking beyond the end of a file). If the file is opened in text mode, only offsets returned by tell() are legal. Use of other offsets causes undefined behavior. Note that not all file objects are seekable. """ pass def tell(self): # real signature unknown; restored from __doc__ 获取当前指针位置 """ tell() -> current file position, an integer (may be a long integer). """ pass def truncate(self, size=None): # real signature unknown; restored from __doc__ 截断数据,仅保留指定之前数据 """ truncate([size]) -> None. Truncate the file to at most size bytes. Size defaults to the current file position, as returned by tell(). """ pass def write(self, p_str): # real signature unknown; restored from __doc__ 写内容 """ write(str) -> None. Write string str to file. Note that due to buffering, flush() or close() may be needed before the file on disk reflects the data written. """ pass def writelines(self, sequence_of_strings): # real signature unknown; restored from __doc__ 将一个字符串列表写入文件 """ writelines(sequence_of_strings) -> None. Write the strings to the file. Note that newlines are not added. The sequence can be any iterable object producing strings. This is equivalent to calling write() for each string. """ pass def xreadlines(self): # real signature unknown; restored from __doc__ 可用于逐行读取文件,非全部 """ xreadlines() -> returns self. For backward compatibility. File objects now include the performance optimizations previously implemented in the xreadlines module. """ pass 2.x
class TextIOWrapper(_TextIOBase): """ Character and line based layer over a BufferedIOBase object, buffer. encoding gives the name of the encoding that the stream will be decoded or encoded with. It defaults to locale.getpreferredencoding(False). errors determines the strictness of encoding and decoding (see help(codecs.Codec) or the documentation for codecs.register) and defaults to "strict". newline controls how line endings are handled. It can be None, '', '\n', '\r', and '\r\n'. It works as follows: * On input, if newline is None, universal newlines mode is enabled. Lines in the input can end in '\n', '\r', or '\r\n', and these are translated into '\n' before being returned to the caller. If it is '', universal newline mode is enabled, but line endings are returned to the caller untranslated. If it has any of the other legal values, input lines are only terminated by the given string, and the line ending is returned to the caller untranslated. * On output, if newline is None, any '\n' characters written are translated to the system default line separator, os.linesep. If newline is '' or '\n', no translation takes place. If newline is any of the other legal values, any '\n' characters written are translated to the given string. If line_buffering is True, a call to flush is implied when a call to write contains a newline character. """ def close(self, *args, **kwargs): # real signature unknown 关闭文件 pass def fileno(self, *args, **kwargs): # real signature unknown 文件描述符 pass def flush(self, *args, **kwargs): # real signature unknown 刷新文件内部缓冲区 pass def isatty(self, *args, **kwargs): # real signature unknown 判断文件是否是同意tty设备 pass def read(self, *args, **kwargs): # real signature unknown 读取指定字节数据 pass def readable(self, *args, **kwargs): # real signature unknown 是否可读 pass def readline(self, *args, **kwargs): # real signature unknown 仅读取一行数据 pass def seek(self, *args, **kwargs): # real signature unknown 指定文件中指针位置 pass def seekable(self, *args, **kwargs): # real signature unknown 指针是否可操作 pass def tell(self, *args, **kwargs): # real signature unknown 获取指针位置 pass def truncate(self, *args, **kwargs): # real signature unknown 截断数据,仅保留指定之前数据 pass def writable(self, *args, **kwargs): # real signature unknown 是否可写 pass def write(self, *args, **kwargs): # real signature unknown 写内容 pass def __getstate__(self, *args, **kwargs): # real signature unknown pass def __init__(self, *args, **kwargs): # real signature unknown pass @staticmethod # known case of __new__ def __new__(*args, **kwargs): # real signature unknown """ Create and return a new object. See help(type) for accurate signature. """ pass def __next__(self, *args, **kwargs): # real signature unknown """ Implement next(self). """ pass def __repr__(self, *args, **kwargs): # real signature unknown """ Return repr(self). """ pass 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 3.x
冒泡排序
#利用新变量互换值 a1 = 123 a2 = 456 temp = a1 a1 = a2 a2 = temp a1 = 456 a2 = 123
#实现列表元组互换 li = [11,33,22,44,55] temp = li[1] li[1] = li[2] li[2]=temp print(li) >>> [11,22,33,44,55]
#把列表里面的所有值进行比较 li = [33,22,10,1] for i in range(len(li)-1): #循环列表次数 # i = 0 1 2 3 #current: li[0] 1 2 3 #next_value: li[1] 2 3 4 #列表li里面没有li[4],因此需要减少一次循环次数 current = li[i] next_value = li[i+1] print(i, current, next_value) >>> 0 33 2 #第一次循环 1 2 10 #第二次循环 2 10 1 #第三次循环
#循环一次列表,仅把一个最大的元素排在最右方
li = [33,2,10,1] for i in range(len(li)-1): #循环列表元素 if li[i] > li[i+1]: #元素互换的条件 temp = li[i] li[i] = li[i+1] li[i + 1] = temp print(li) >>> [2, 10, 1, 33]
li = [33,2,10,1] for i in range(len(li)-1): #元素内部从左往右循环比较三次,等于列表长度减1那么多次,如列表4个元素,两两比较,需要比较三次1-(33, 2), 2-(2,10), 3-(10, 1) if li[i] > li[i+1]: temp = li[i] li[i] = li[i+1] li[i + 1] = temp print(li) >>> [2,10,1,33]
li = [33,2,10,1] for j in range(1, len(li)): #由于i循环每完成一次,下一次i循环排序的元素就减少一次, j的数值应为1,2,3 到数列的长度为止。 #j: 1 ,2 ,3, i循环中两两比较的次数 for i in range(len(li)-j): #元素内部循环比较完成一次,得到最右边的一个最大元素,下一次循环比较的元素就减少一个,j代表每次完成循环减少的排序的元素。 if li[i] > li[i+1]: temp = li[i] li[i] = li[i+1] li[i + 1] = temp print(li) >>> [1, 2, 10, 33]
递归
递归指的是这样一个数列:1、1、2、3、5、8、13、21、……
递归满足2个条件:
1)有反复执行的过程(调用自身)
2)有跳出反复执行过程的条件(递归出口)
递归执行过程中参数传递过程
def f1(): return "f1" #8. 执行f1(),返回"f1", f1返回给函数调用者f1()="f1"=>f2()=>f3()=>f4(),最后有ret接受返回值“f1” def f2(): r = f1() #6. 执行f2(),得到 r = f1() return r #7. r = f1(), 返回r,即返回执行f1() def f3(): r = f2() #4. 执行f3(),得到 r = f2() return r #5. r = f2(), 返回r,即返回执行f2() def f4():
r = f3() #2.执行f4(),得到 r = f3() return r #3.r = f3(), 返回r,即返回执行f3() ret = f4() # 1.解释器读取函数,把f1,f2,f3,f4的函数存入内存,执行函数f4(), ret接受f4返回值r
print(ret)
def f4(a1, a2): print(a1, a2) #a1 = 0, a2 = 1,a3 = 1 #a1 = 1, a2 = 1, a3 = 2 #a1 = 1, a2 = 2, a3 = 3 a3 = a1 + a2 # f4(a2, a3) #嵌套上面的参数循环执行函数 f4(0, 1) >>> 0 1 1 1 1 2 2 3 3 5 5 8 8 13 13 21 21 34 34 55 55 89 ...
练习:利用递归获取斐波那契数列中的第 10 个数,并将该值返回给调用者。
def f5(depth, a1, a2): #depth数列的第n个数
if depth == 10: return a1 #数列第十个数的返回值,最终有启始的函数'ret'接受 a3 = a1 + a2 r = f5(depth +1, a2, a3) return r ret = f5(1,0,1)#数值0为第一个斐波那契的数值 print(ret) >>> 34
装饰器
装饰器用于装饰某个函数或者方法或者类,在调用者调用方式不变的情况下,可以在函数执行前或执行后做其他操作。
装饰器本质,将 原函数 封装到 新的函数里面(),使执行新函数时,既可以实现新函数的功能,有可以执行就函数的功能。
def outer(func):#参数func = 以原来的f1函数作为参数 def inner():#inner函数作为新的f1函数执行 print("hello") r = func()#由于outer(func)的参数为f1,此处执行原来的f1函数 print("end") return r return inner #@outer inner = f1 @outer #f1 = outer(f1) 1.执行outer函数,并且将其下面的函数名f1当做参数,func = f1;
2.将outer的返回值inner重新赋值给f1,f1=(outer的返回值)=inner, 执行f1() = 执行inner() def f1(): print("F1")
return ooo def f2(): print("F2") def f3(): print("F3") """ . . . """ def f100(): print("F100")
f1() >>> hello F1 end
ooo
只要函数应用装饰器,那么函数就被重新定义为:装饰器的内层函数。
装饰器装饰含两个参数的函数
def outer(func): def inner(a1, a2): print("123") ret = func(a1, a2) print("456") return ret return inner @outer #inner = index(a1, a2),index函数被装饰到inner函数里面, #执行index函数是需要两个参数,因此装饰器函数也需要两个参数inner(a1,a2)。 #装饰器内部执行func() = 执行index(),因此也需要在func函数中加入两个参数。func(a1, a2) def index(a1, a2): print("执行函数") return a1 + a2 ret = index(1, 2) print(ret)
装饰器装饰含N个参数的函数
def f1(*args,**kwargs):#多参数函数 print(args) print(kwargs) f1(11, 22, 33, 44, 55, 66, 77, 88, k1=123, k2=321)
>>>
(11, 22, 33, 44, 55, 66, 77, 88)
{'k2': 321, 'k1': 123}
def outer(func): def inner(*args, **kwargs):# print(args) ret = func(*args, **kwargs)# print(kwargs) return ret return inner @outer def index(a1, a2, k1=123, k2=456): print("执行函数") return a1 + a2 ret = index(10, 20, k1=123, k2=456) print(ret) >>> (10, 20) 执行函数 {'k1': 123, 'k2': 456} 30
多个装饰器装饰同一个函数
def outer_0(func): def inner(*args, **kwargs): print("python 3.5") ret = func(*args, **kwargs) return ret return inner def outer(func): def inner(*args, **kwargs): print(args) ret = func(*args, **kwargs) print(kwargs) return ret return inner @outer_0 @outer def index(a1, a2, k1=123, k2=456): print("执行函数") return a1 + a2 >>> python 3.5 (10, 20) 执行函数 {'k1': 123, 'k2': 456} 30
多装饰器嵌套原理
# @outer: inner = index, outer(func) = outer(index) # inner = 新的 index 函数 # index(*args, **kwargs): # print(args) # ret = index(*args, **kwargs) # print("执行函数") # return a1 + a2 # print(kwargs) # return ret #@outer0:inner = 新的 index 函数 + 新的 inner, outer0(func) = outer0(inner(index)) #inner =out0 + index(*args, **kwargs) 函数 + #index(*args, **kwargs): # print("python 3.5") # print(args) # print("执行函数") # return a1 + a2 # print(kwargs) # return ret
装饰器总结 @
把index函数作为outer的参数去执行outer函数
index的整体放入内存 当内层函数inner中对index进行调用它作为一个新的函数
@outer
1. 执行outer函数,将index作为参数传递
2. 将outer的返回值,重新赋值给index