###############高階函數#################
一 函數
(1)函數本身也可以賦值給變量,即:變量可以指向函數。
截圖:
(2)函數名其實就是指向函數的變量!
截圖:
上述操作發現:abs爲函數名,給abs=1重新賦值後,abs已不是函數,而是一個整數。
二 高階函數
變量可以指向函數,函數的參數能接收變量,那麼一個函數就可以接收另
一個函數作爲參數,這種函數就稱之爲高階函數。
1.map函數
map()函數接收兩個參數,一個是函數,一個是序列, map 將傳入的函數依次作用到序列的每個元素,並把結果作爲新的 list 返回。
(不需要 map() 函數,寫一個循環,也可以計算出結果.map函數)
截圖:
練習:
把這list列表中的所有數字轉爲字符串;([1,2,3]---['1','2','3'])
截圖:
2.reduce函數
reduce 把一個函數作用在一個序列[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce 把結果繼續和序列的下一個元素做累積計算。
截圖:
綜合編程:
寫出把 str 轉換爲 int 的函數(eg:'12345'--12345)
截圖:
reduce函數map/reduce練習題:
利用 map() 函數,把用戶輸入的不規範的英文名字,變爲首字母大寫,其他小寫的規範名字。輸入: ['adam', 'LISA', 'barT'] ,輸出: ['Adam', 'Lisa','Bart'] 。
def fun(x): ##### 定義一個函數,
return x.title()
li = ['adam', 'LISA', 'barT'] ###定義一個列表
print map(fun ,li)
截圖:
Python 提供的 sum() 函數可以接受一個 list 並求和,請編寫一個 prod()函數,可以接受一個 list 並利用 reduce() 求積。
截圖:
3.filter函數
filter() 也接收一個函數和一個序列。和 map() 不同的時,filter() 把傳入的函數依次作用於每個元素,然後根據返回值是 True
還是 False 決定保留還是丟棄該元素。
在一個 list 中,刪掉偶數,只保留奇數:
截圖:
在一個 list 中,刪掉奇數,只保留偶數:
截圖:
習題:
把一個序列中的空字符串刪請嘗試用 filter() ;
用 filter()刪除 1~100 的素數;
4.sorted函數
排序也是在程序中經常用到的算法。 無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小。
通常規定如下:
x < y, return -1
x == y, return 0
x > y, return 1
python內置的 sorted() 函數就可以對 list 進行排序;
如果要倒序排序呢?
如果要對字符串進行排序呢?sorted函數倒序排序
In [1]: t=(12,56,432,56,954) ####定義一個元組
In [2]: sorted(t) #####內置函數 :默認從小到大排列
Out[2]: [12, 56, 56, 432, 954]
In [4]: def reversed_cmp(x,y): #####自己定義函數:從大到小排列。(整數)
if x>y :
...: return -1
...: elif x<y :
...: return 1
...: else:
...: return 0
...:
In [5]: sorted(t,reversed_cmp) ###高階函數
Out[5]: [954, 432, 56, 56, 12]
In [6]: li=["xiaoming","huangrong"] ####定義一個列表
In [7]: sorted(li) #####內置函數 :默認從小到大排列,按字母所對應的acsii碼大小排列。
Out[7]: ['huangrong', 'xiaoming']
In [20]: li=['xiaoming', 'huangrong', 'Huangrong']
In [24]: "huangrong">"Huangrong"
Out[24]: True
In [17]: def ignore_case_cmp(x,y):#####自己定義函數:從大到小排列(字母)
lower1=x.lower()
lower2=y.lower()
if lower1<lower2:
return -1
elif lower1>lower2:
....: return 1
....: else:
....: return 0
....:
In [21]: sorted(li,ignore_case_cmp) ###高階函數
Out[21]: ['huangrong', 'Huangrong', 'xiaoming']
5.函數作爲返回值
高階函數除了可以接受函數作爲參數外,還可以把函數作爲結果值返回。
(1)
def lazy_sum(*args): 1
def sum(): 5
ax = 0 6
for n in args: 7
ax = ax + n 8
return ax 9
return sum 3
f = lazy_sum(1,2,3,4) 2 #調用 lazy_sum() 時,返回的並不是求和結果,而是求和函數
f() 4,10 #調用函數 f 時,才真正計算求和的結果函數作爲返回值調用 lazy_sum() 時,每次調用都會返回一個新的函數,即使傳入相同的參數
(2)
def warp_sum(*args):定義一個把求和函數作爲內置函數的函數:執行顯示錶達式(閉包)
def my_sum(): ########定義一個求和的函數:執行直接求和
sum_num=0
for i in args:
if not isinstance(i,(int,float)):
print "type error"
sum_num = sum_num +i
return sum_num
return my_sum
f = warp_sum(1,4,2) ####給函數賦值
print f() #######打印f
截圖:
(3)
def count(): #########定義一個函數
fs=[] ######定義一個空列表
for i in range(1,4): ###循環遍歷
def f():
return i*i
fs.append(f) ####將f添加到fs列表,f是函數的存儲地址
return fs
f1,f2,f3,=count()
print f1 ########顯示函數的存儲地址
print f2
print f3
截圖:
(4)
def count():
fs=[]
for i in range(1,4):
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3,=count()
print f1() #############顯示的是數值,可是數值都爲9
print f2()
print f3()
截圖:
(5)
def count():
fs=[]
for i in range(1,4):
def f(j):
def g():##########在f函數裏嵌套一個g函數
return j*j
return g
fs.append(f(i))
return fs
f1,f2,f3,=count()
print f1() ####返回的是各自對應值;1,4,9
print f2()
print f3()
6.匿名函數
因爲匿名函數沒有名字,不必擔心函數名衝突。
匿名函數可以跳過給函數棧分配空間
當我們在傳入函數時,有些時候,不需要顯式地定義函數,直接傳入匿名函數更方便。
關鍵字 lambda 表示匿名函數,冒號前面的 x 表示函數參數匿名函數
匿名函數有只能有一個表達式,不用寫 return ,返回值就是該表達式的結果。
此外,匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變量,再利用變量來調用該函數;
也可以把匿名函數作爲返回值返回
def pow1(x):
return x*x
print map(pow1,range(1,11))
print map(lambda x:x*x,range(1,11))
f= lambda :1
print f
截圖:
f=lambda x,y=2:x**y
print f(2,3)
print (2)
截圖:
f = lambda *x:map(lambda x:x+x,x)
print f(1,2,3,4)
f = lambda **kwargs:kwargs.items()
print f (name='fentiao',age=5)
x=1
oper = "*"
y = 2
d={
"+":lambda x,y:x+y,
"-":lambda x,y:x+y,
"*":lambda x,y:x*y,
"/":lambda x,y:x/y
}
if oper not in d.keys():
print 'input +,-,*,/'
7 裝飾器
裝飾器就是用來裝飾函數。
不修改函數的源代碼。
函數的調用方式沒有改變。
想要增強原有函數的功能;
但不希望修改now()函數的定義;
在代碼運行期間動態增加功能的方式;裝飾器
定義的裝飾器實質是返回函數的高階函數。(試試下面的裝飾器)
import time
def timeIt(func):
def warp(arg):
start = datetime.datetime.now()
func(arg)
end = datetime.datetime.now()
cost = end - start
print "execute %s spend %s" % (func.__name__,cost.total_seconds())
return warp
@timeIt # 這裏是 python 提供的一個語法糖
def func(arg):
time.sleep(arg)
func(3)
import time
def timmer (func):
start_time = time.time()
func()
stop_time=time.time()
return stop_time-start_time
def hello2():
print 'hello2....'
time.sleep(2)
print timmer(hello2)
print d[oper](x,y)
import time
def logger (func):
def dec():
start_time = time.time()
func()
stop_time=time.time()
return '%s run %f s'%(func.__name__,stop_time-start_time)
return dec
@logger
def hello2():
print 'hello2....'
time.sleep(2)
print hello2()
#############文件操作#################
一 文件讀寫
Python 內置了讀寫文件的函數,用法和 C 是兼容的。
操作系統不允許普通的程序直接操作磁盤,所以,讀寫文件就是請求操作系統打開一個文件對象(又稱文件描述符),然後,通過操作系統提供的接
口從這個文件對象操作;
1.思考:
把大象放進冰箱的過程。
2.思考文件讀寫的過程:
(1). 打開文件
(2). 向文件中寫入內容;
(3). 關閉文件文件讀寫
3. 打開文件
f = open('/root/hello')
# 如果文件不存在, open() 函數就會拋出一個 IOError 的錯誤,並且給出錯誤碼和詳細的信息告訴你文件不存在;
4.讀取文件
f.read()
#如果文件打開成功,接下來,調用 read() 方法可以一次讀取文件的全部內容;
5.關閉文件
f.close()
#文件使用完畢後必須關閉,因爲文件對象會佔用操作系統的資源。
6.思考:
read()會一次性讀取文件的全部內容,如果文件有 10G,內存就爆了。怎麼解決?
如果文件很小, read() 一次性讀取最方便;
如果不能確定文件大小,反覆調用 read(size)
比較保險;如果是配置文件,調用 readlines()文件讀寫
截圖:
7. 二進制文件
要讀取二進制文件,比如圖片、視頻等等,用 'rb' 模式打開文件即可
>>> f = open('/root/test.jpg', 'rb')
>>> f.read()
'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進制表示的字節文件讀寫
8. 字符編碼
要讀取非 ASCII 編碼的文本文件,就必須以二進制模式打開,再解碼,Python 還提供了一個 codecs 模塊幫我們在讀文件時自動轉換編碼,直接讀出 unicode。
import codecs
with codecs.open('/Users/michael/gbk.txt', 'r', 'gbk') as f:
f.read() # u'\u6d4b\u8bd5'
二 open函數的模式
r 以讀的方式打開,定位到文件開頭 , 默認的 mode
r+ 以讀寫的方式打開,定位文件開頭 , 可以寫入內容到文件
w 以寫的方式打開,打開文件的時候會清空文件的內容,並且不能讀
w+ 以讀寫的方式打開,定位到文件頭,並且打開文件的時候也會清空文件的內容
a 以寫的方式打開,定位到文件的末尾,是一個追加的操作 , 但並不允許讀
a+ 以讀寫的方式打開,定位到文件的末尾,追加的方式。
在使用以上 mode 打開文件的時候,如果增加了b 模式,表示以二進制方式打開
截圖:
三 文件的其它操作
1.f.flush()函數,將緩衝區的內容寫入到硬盤中
2.f.seek(offset[,whence]),offset 表示移動多少字節, whence 爲 1 的時候表示相對於當前位置移動的;當 2 的時候從文件的末尾往後移動,但不一定所有的平臺都支持;默認爲 0 表示從文件開頭往後移動
3.f.tell()函數,返回當前文件指針的偏移量:文件的其它操作
4.fileno() 函數,返回當前的文件描述符,一個數字
5.isatty() 函數,當前打開的文件是否是一個終端設備
6.closed 屬性,當前文件是否關閉 ,|True,False, f.closed
7.file 對象是一個迭代器:
next() 方法 , 一行一行的讀 , 每次讀取一行
四 with語法
一般情況打開一個文件,經過操作之後,都要顯式的執行xx.close() 將文件關閉 .with 用於需要打開、關閉成對的操作,可以自動關閉打開對象 .
with expression as obj:# 將打開的對象賦值給 obj
expression
#obj 的作用域只在 with 語句中