高階函數,文件

###############高階函數#################

一 函數

(1)函數本身也可以賦值給變量,即:變量可以指向函數。

截圖:

wKioL1lo3PuyR6haAACw6tIvVv0626.png-wh_50



(2)函數名其實就是指向函數的變量!

截圖:

wKioL1lo3cny8PjJAACa2mC8jMk484.png-wh_50


上述操作發現:abs爲函數名,給abs=1重新賦值後,abs已不是函數,而是一個整數。




二 高階函數


變量可以指向函數,函數的參數能接收變量,那麼一個函數就可以接收另

一個函數作爲參數,這種函數就稱之爲高階函數。


1.map函數

map()函數接收兩個參數,一個是函數,一個是序列, map 將傳入的函數依次作用到序列的每個元素,並把結果作爲新的 list 返回。

(不需要 map() 函數,寫一個循環,也可以計算出結果.map函數)

截圖:

wKioL1lo3inQUIlWAADN50aItH8676.png-wh_50

練習: 

把這list列表中的所有數字轉爲字符串;([1,2,3]---['1','2','3'])

截圖:


wKiom1lo2NXSbljXAAA6TMSxL_s454.png-wh_50

2.reduce函數


reduce 把一個函數作用在一個序列[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce 把結果繼續和序列的下一個元素做累積計算。

截圖:

wKiom1lo3irAuXdhAACFmOD1ZZc768.png-wh_50

wKiom1lo2OODtIn6AABlA41WNtA211.png-wh_50

wKioL1lo3o2gTYX8AACQ-2GJD1c713.png-wh_50


綜合編程:

寫出把 str 轉換爲 int 的函數(eg:'12345'--12345)

截圖:


wKioL1lo2N2Q1DE-AABSeg689fk594.png-wh_50


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() 求積。

截圖:

wKiom1lo38-Dzg5dAACC9xZ46ic113.png-wh_50



3.filter函數


filter() 也接收一個函數和一個序列。和 map() 不同的時,filter() 把傳入的函數依次作用於每個元素,然後根據返回值是 True

還是 False 決定保留還是丟棄該元素。


在一個 list 中,刪掉偶數,只保留奇數:

截圖:

wKiom1lo3o7S9JNzAABLZ9r_T3k249.png-wh_50

在一個 list 中,刪掉奇數,只保留偶數:

截圖:

wKioL1lo3o7hTBqkAABO_vZl-xk331.png-wh_50


習題:


把一個序列中的空字符串刪請嘗試用 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

截圖:

wKioL1lo2s-Rt0eJAAC1gZ0BA9o562.png-wh_50


(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

截圖:

wKioL1lo2OWSAcEdAAD886HnvKU724.png-wh_50


(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()

截圖:

wKioL1lo2tCj2T0VAADbZdlulpo134.png-wh_50


(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()

wKiom1lo2tLj0xFhAAEAGv7C9JQ525.png-wh_50


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

截圖:

wKioL1lo2tPCzglWAADGrmv7EEs422.png-wh_50



f=lambda x,y=2:x**y

print f(2,3)

print (2) 

截圖:


wKiom1lo2tSjvwWZAABfwxXqjro899.png-wh_50


f = lambda  *x:map(lambda  x:x+x,x)

print f(1,2,3,4)

wKioL1lo2-7wxNSEAABmXRHY0XE506.png-wh_50

f = lambda  **kwargs:kwargs.items()

print f (name='fentiao',age=5)

wKiom1lo2--hzMxRAABjzBx6M7w709.png-wh_50

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 +,-,*,/'

wKioL1lo2_Dy***yAADJHwUFoHk943.png-wh_50

wKiom1lo2_GgZFeZAADt718AA-w696.png-wh_50

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)

wKioL1lo2_LSEkBTAADCn0Q2SL4431.png-wh_50


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()


wKiom1lo3PrSkUbbAAEE-wv3Zqg277.png-wh_50




#############文件操作#################


一 文件讀寫

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()文件讀寫

截圖:

wKioL1lo4XLwmfzFAACH0MKSFd0944.png-wh_50

wKioL1lo4XSDFPdkAADnIL6aSnU586.png-wh_50

wKioL1lo4c_DfV7KAAEPkoTPMKo075.png-wh_50

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 模式,表示以二進制方式打開

截圖:

wKioL1lo4E_R2Sh_AAFX-tyoEV0318.png-wh_50

wKioL1lo4FGC8qbRAAC7sQ1Pt_w282.png-wh_50

wKiom1lo4FKjYG8FAADFsUur6ls279.png-wh_50

wKioL1lo4FOgUeNkAAC2bNXSiyo155.png-wh_50

wKiom1lo4OSQ2Hx4AAA7Hlk-Uvc823.png-wh_50

wKioL1lo4OfSH189AAB_q5KJKJY773.png-wh_50

wKioL1lo4ObRmV-lAAA6gSGV0Mk069.png-wh_50

wKiom1lo4OijxxsXAABGK_7BGro021.png-wh_50

wKioL1lo4OmQPh_dAABWftZqECY969.png-wh_50


三 文件的其它操作


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() 方法 , 一行一行的讀 , 每次讀取一行

wKiom1lo4i2Rg4JPAAD9N_ppuNc895.png-wh_50

wKioL1lo4i6A-RuZAAGwSpMK6kw972.png-wh_50

wKioL1lo4i_RkeKrAADBqdFYBWo685.png-wh_50

wKiom1lo4jDjR4QLAADptSl_xos898.png-wh_50


四 with語法



一般情況打開一個文件,經過操作之後,都要顯式的執行xx.close() 將文件關閉 .with 用於需要打開、關閉成對的操作,可以自動關閉打開對象 .

with expression as obj:# 將打開的對象賦值給 obj

expression

#obj 的作用域只在 with 語句中


wKioL1lo4iuAj8z3AAC4_LVsaT8834.png-wh_50


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章