Python基礎:Python函數、文件操作、遞歸
函數參數
函數參數包括位置參數,關鍵字參數,動態參數(*args, **args)三種。
傳參的過程是形式參數的賦值。
*args傳入的參數是元組形式,**args傳入的參數是字典形式。
示例代碼如下:(這部分直接看代碼實例會更清楚靜態參數與動態參數如何混用)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # def story(**kwargs): 4 # return ‘Once upon a time,there was a ‘ 5 # ‘%(job)s called %(name)s.‘ % kwargs 6函數參數示例# print(story(job = ‘king‘,name = ‘bolen‘)) 7 # 8 # def power(x,y,*others): 9 # if others: 10 # print(‘received redundant parameters:‘,others) 11 # return pow(x,y) 12 # power(2,3,) 13 14 def interval(start,stop = None,step = 1): 15 if stop is None: 16 start,stop=0,start17 result = [] 18 i = start 19 while i < stop: 20 result.append(i) 21 i+=step 22 return result 23 24 -----------------------shell excute------------------------------- 25 >>> story(job = ‘king‘,name = ‘bolen‘) 26 ‘Once upon a time,there was a king called bolen.‘ 27>>> parms = {‘job‘:‘engineer‘,‘name‘:‘jack‘} 28 >>> story(**parms) 29 ‘Once upon a time,there was a engineer called jack.‘ 30 >>> del parms[‘job‘] 31 >>> parms 32 {‘name‘: ‘jack‘} 33 >>> story(job = ‘小王子‘,**parms) 34 ‘Once upon a time,there was a 小王子 called jack.‘ 35 36 >>> power(2,3) 37 8 38 >>> power(y=3,x=2) 39 8 40 >>> parms = (5,)*2 41 >>> type(parms) 42 <class ‘tuple‘> 43 >>> power(*parms) 44 3125 45 >>> parms 46 (5, 5) 47 48 49 >>> interval(10) 50 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 51 >>> interval(1,6) 52 [1, 2, 3, 4, 5] 53 >>> interval(2,12,3) 54 [2, 5, 8, 11] 55 >>> power(*interval(3,7)) 56 received redundant parameters: (5, 6) 57 81 58
變量作用域
函數內部的變量稱為局部變量,全局無法訪問局部變量,函數內部正常也無法訪問全局變量,除非以如下方式:
函數內讀取全局變量:(慎重引用全局變量,容易出錯)
1 >>> def com(para): 2 print(para+globals()[‘para‘]) 3 >>> com(‘yingying‘) 4 yingyingbolen
函數內聲明全局變量:
1 >>> def ch_global(): 2 global x 3 x +=1 4 >>> x = 1 5 >>> ch_global() 6 >>> x 7 2
Python內置函數
詳細介紹請點擊:官網內置函數詳解
Python文件操作:open函數和with open(管理上下文)
open函數用於文件處理。一般步驟是打開文件,然後操作文件。
1 文件句柄 = open(‘文件路徑‘,‘模式‘)
句柄是WONDOWS用來標識被應用程序所建立或使用的對象的唯一整數,WINDOWS使用各種各樣的句柄標識諸如應用程序實例,窗口,控制,位圖,GDI對象等等。句柄是一個標識符,是拿來標識對象或者項目的,它就象我們的姓名一樣,每個人都會有一個,不同的人的姓名不一樣,但是,也可能有一個名字和你一樣的人。從數據類型上來看它只是一個16位的無符號整數。應用程序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之後其他的WINDOWS函數就可以使用該句柄,以引用相應的對象。文件句柄在文件I/O中,要從一個文件讀取數據,應用程序首先要調用操作系統函數並傳送文件名,並選一個到該文件的路徑來打開文件。該函數取回一個順序號,即文件句柄(file handle),該文件句柄對於打開的文件是唯一的識別依據。要從文件中讀取一塊數據,應用程序需要調用函數ReadFile,並將文件句柄在內存中的地址和要拷貝的字節數傳送給操作系統。當完成任務後,再通過調用系統函數來關閉該文件。
打開後獲得該文件句柄,後面通過此文件句柄對文件操作。
一、打開文件
打開文件的模式有:
- r ,只讀模式【默認】
- w,只寫模式【不可讀;不存在則創建;存在則清空內容;】
- x, 只寫模式【不可讀;不存在則創建,存在則報錯】
- a, 追加模式【可讀; 不存在則創建;存在則只追加內容;】
"+" 表示可以同時讀寫某個文件
- r+, 讀寫【可讀,可寫】
- w+,寫讀【可讀,可寫】
- x+ ,寫讀【可讀,可寫】
- a+, 寫讀【可讀,可寫】
"b"表示以字節的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
註:以b方式打開時,讀取到的內容是字節類型,寫入時也需要提供字節類型。
二、文件操作
1 class TextIOWrapper(_TextIOBase): 2 """ 3 Character and line based layer over a BufferedIOBase object, buffer. 4 5 encoding gives the name of the encoding that the stream will be 6 decoded or encoded with. It defaults to locale.getpreferredencoding(False). 7 8 errors determines the strictness of encoding and decoding (see 9 help(codecs.Codec) or the documentation for codecs.register) and 10 defaults to "strict". 11 12 newline controls how line endings are handled. It can be None, ‘‘, 13 ‘\n‘, ‘\r‘, and ‘\r\n‘. It works as follows: 14 15 * On input, if newline is None, universal newlines mode is 16 enabled. Lines in the input can end in ‘\n‘, ‘\r‘, or ‘\r\n‘, and 17 these are translated into ‘\n‘ before being returned to the 18 caller. If it is ‘‘, universal newline mode is enabled, but line 19 endings are returned to the caller untranslated. If it has any of 20 the other legal values, input lines are only terminated by the given 21 string, and the line ending is returned to the caller untranslated. 22 23 * On output, if newline is None, any ‘\n‘ characters written are 24 translated to the system default line separator, os.linesep. If 25 newline is ‘‘ or ‘\n‘, no translation takes place. If newline is any 26 of the other legal values, any ‘\n‘ characters written are translated 27 to the given string. 28 29 If line_buffering is True, a call to flush is implied when a call to 30 write contains a newline character. 31 """ 32 def close(self, *args, **kwargs): # real signature unknown 33 關閉文件 34 pass 35 36 def fileno(self, *args, **kwargs): # real signature unknown 37 文件描述符 38 pass 39 40 def flush(self, *args, **kwargs): # real signature unknown 41 刷新文件內部緩沖區 42 pass 43 44 def isatty(self, *args, **kwargs): # real signature unknown 45 判斷文件是否是同意tty設備 46 pass 47 48 def read(self, *args, **kwargs): # real signature unknown 49 讀取指定字節數據 50 pass 51 52 def readable(self, *args, **kwargs): # real signature unknown 53 是否可讀 54 pass 55 56 def readline(self, *args, **kwargs): # real signature unknown 57 僅讀取一行數據 58 pass 59 60 def seek(self, *args, **kwargs): # real signature unknown 61 指定文件中指針位置 62 pass 63 64 def seekable(self, *args, **kwargs): # real signature unknown 65 指針是否可操作 66 pass 67 68 def tell(self, *args, **kwargs): # real signature unknown 69 獲取指針位置 70 pass 71 72 def truncate(self, *args, **kwargs): # real signature unknown 73 截斷數據,僅保留指定之前數據 74 pass 75 76 def writable(self, *args, **kwargs): # real signature unknown 77 是否可寫 78 pass 79 80 def write(self, *args, **kwargs): # real signature unknown 81 寫內容 82 pass 83 84 def __getstate__(self, *args, **kwargs): # real signature unknown 85 pass 86 87 def __init__(self, *args, **kwargs): # real signature unknown 88 pass 89 90 @staticmethod # known case of __new__ 91 def __new__(*args, **kwargs): # real signature unknown 92 """ Create and return a new object. See help(type) for accurate signature. """ 93 pass 94 95 def __next__(self, *args, **kwargs): # real signature unknown 96 """ Implement next(self). """ 97 pass 98 99 def __repr__(self, *args, **kwargs): # real signature unknown 100 """ Return repr(self). """ 101 pass 102 103 buffer = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 104 105 closed = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 106 107 encoding = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 108 109 errors = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 110 111 line_buffering = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 112 113 name = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 114 115 newlines = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 116 117 _CHUNK_SIZE = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 118 119 _finalizing = property(lambda self: object(), lambda self, v: None, lambda self: None) # default 120 121 3.xPython3中的文件操作
三、管理上下文
由於文件讀寫時都有可能產生IOError
,一旦出錯,後面的f.close()
就不會調用。所以,為了保證無論是否出錯都能正確地關閉文件,我們可以使用try ... finally
來實現:
1 try: 2 f = open(‘/path/to/file‘, ‘r‘) 3 print(f.read()) 4 finally: 5 if f: 6 f.close() 7
但是每次都這麽寫實在太繁瑣,所以,Python引入了with
語句來自動幫我們調用close()
方法:
1 with open(‘/path/to/file‘, ‘r‘) as f: 2 print(f.read()) 3
這和前面的try ... finally
是一樣的,但是代碼更佳簡潔,並且不必調用f.close()
方法。
在Python 2.7 及以後,with又支持同時對多個文件的上下文進行管理,即:
1 with open(‘log1‘) as obj1, open(‘log2‘) as obj2: 2 pass 3
1 import sys 2 import json 3 with open (‘c:/Users/zliyong/filo.txt‘,‘a+‘,encoding=‘utf-8‘) as f: 4 #f.write(‘first line\nsecondline\n3rd line\n 4rd line‘) 5 # f.tell()#查看當前指針位置 6 # f.seek(2)#指定當前指針位置 7 ret = f.truncate(100) #從指定位置向前截取 8 print(f.tell()) 9 print(f.read()) 10 for line in f.readlines(): 11 print(line.strip())Python3中的文件操作實例
如果文件很小,read()
一次性讀取最方便;如果不能確定文件大小,反復調用read(size)
比較保險;如果是配置文件,調用readlines()
最方便。
像open()
函數返回的這種有個read()
方法的對象,在Python中統稱為file-like Object。除了file外,還可以是內存的字節流,網絡流,自定義流等等。file-like Object不要求從特定類繼承,只要寫個read()
方法就行。
StringIO
就是在內存中創建的file-like Object,常用作臨時緩沖。
二進制文件
前面講的默認都是讀取文本文件,並且是UTF-8編碼的文本文件。要讀取二進制文件,比如圖片、視頻等等,用‘rb‘
模式打開文件即可:
1 >>> f = open(‘/Users/michael/test.jpg‘, ‘rb‘) 2 >>> f.read() 3 b‘\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...‘ # 十六進制表示的字節 4
字符編碼
要讀取非UTF-8編碼的文本文件,需要給open()
函數傳入encoding
參數,例如,讀取GBK編碼的文件:
1 >>> f = open(‘/Users/michael/gbk.txt‘, ‘r‘, encoding=‘gbk‘) 2 >>> f.read() 3 ‘測試‘ 4
遇到有些編碼不規範的文件,你可能會遇到U
nicodeDecodeError
,因為在文本文件中可能夾雜了一些非法編碼的字符。遇到這種情況,open()
函數還接收一個errors
參數,表示如果遇到編碼錯誤後如何處理。最簡單的方式是直接忽略:
1 >>> f = open(‘/Users/michael/gbk.txt‘, ‘r‘, encoding=‘gbk‘, errors=‘ignore‘)
寫文件註意事項:
可以反復調用f.write來進行寫文件,但是一定要記得用f.close來關閉文件。因為操作系統在往磁盤裏寫文件時,往往不會立即寫入磁盤,而是放在內存中緩存起來,待空閑了再慢慢進行寫操作,所以只有調用f.close()方法才能保證操作系統文件完整寫入到磁盤,否則經常會使文件部分寫入磁盤,剩下的丟失了。
操作文件和目錄
Python中的內置os模塊提供了調用系統接口函數的功能,實現簡單的系統操作。
1 >>>import os 2 >>>os.name() #獲取操作系統名字 3 ‘nt‘ 4 >>> os.environ #獲取操作系統全部的環境變量 5 >>> os.environ.get(‘PATH‘)#獲取操作系統中某個環境變量的值 6 7 8
註意:操作文件和目錄的函數一部分放在os
模塊中,一部分放在os.path
模塊中。創建、刪除目錄,路徑拼接等可以如下調用:
1 >>> os.path.abspath(‘.‘) 2 ‘C:\\Users\\zliyong\\AppData\\Local\\Programs\\Python\\Python35‘ 3 >>> os.path.join(‘Users/zliyong‘,‘test.dir‘) #路徑拼接 4 ‘Users/zliyong\\test.dir‘ 5 >>> os.mkdir(‘c:/Users/zliyong/test.dir‘) 6 >>> os.rmdir(‘c:/Users/zliyong/test.dir‘) 7 >>> os.path.split(‘c:/Users/zliyong/test.dir‘) 8 (‘c:/Users/zliyong‘, ‘test.dir‘) 9 >>> os.path.splitext(‘c:/Users/zliyong/test.dir/test.txt‘) 10 (‘c:/Users/zliyong/test.dir/test‘, ‘.txt‘) 11 >>> os.rename(‘c:/Users/zliyong/test.dir‘,‘c:/Users/zliyong/pyrename.dir‘)
但是復制文件的函數居然在os
模塊中不存在!原因是復制文件並非由操作系統提供的系統調用。理論上講,我們通過上一節的讀寫文件可以完成文件復制,只不過要多寫很多代碼。
幸運的是shutil
模塊提供了copyfile()
的函數,你還可以在shutil
模塊中找到很多實用函數,它們可以看做是os
模塊的補充。
1 import shutil 2 >>> shutil.copyfile(‘c:/Users/zliyong/pyrename.dir/test.txt‘,‘c:/Users/zliyong/pyrename.dir/test2.txt‘) 3 ‘c:/Users/zliyong/pyrename.dir/test2.txt‘
最後看看如何利用Python的特性來過濾文件。比如我們要列出當前目錄下的所有目錄,只需要一行代碼:
1 >>> [x for x in os.listdir(‘.‘) if os.path.isdir(x)] 2 [‘DLLs‘, ‘Doc‘, ‘include‘, ‘Lib‘, ‘libs‘, ‘Scripts‘, ‘tcl‘, ‘Tools‘] 3 >>> [x for x in os.listdir(‘.‘) if os.path.isfile(x) and os.path.splitext(x)[1]==‘.py‘] 4 []
lambda表達式
lambda表達式又稱為匿名函數,適用於某些簡單函數的語法糖。如下這個lambda表達式結合列表推導式的例子是很tricky的:
1 >>> result = [lambda x: x + i for i in range(10)] 2 >>> print(result[0](10)) 3 19 4 >>> print(result) 5 [<function <listcomp>.<lambda> at 0x000001D664C7C7B8>, <function <listcomp>.<lambda> at 0x000001D667100F28>, <function <listcomp>.<lambda> at 0x000001D667105048>, <function <listcomp>.<lambda> at 0x000001D6671050D0>, <function <listcomp>.<lambda> at 0x000001D667105158>, <function <listcomp>.<lambda> at 0x000001D6671051E0>, <function <listcomp>.<lambda> at 0x000001D667105268>, <function <listcomp>.<lambda> at 0x000001D6671052F0>, <function <listcomp>.<lambda> at 0x000001D667105378>, <function <listcomp>.<lambda> at 0x000001D667105400>]
首先執行range函數,然後生成10個lamda函,當調用result函數時i=9,所以result是一個10個元素都是19的列表。
遞歸
Python基礎:Python函數、文件操作、遞歸