1. 程式人生 > 其它 >reserve函式python_python學習筆記5之越來越難(函式)

reserve函式python_python學習筆記5之越來越難(函式)

技術標籤:reserve函式python

5 函數語言程式設計

5.1高階函式:可以用其他函式作為自己引數的函式

推論,首先,一個函式就是用函式名指向已經內建好的函式,例abs(),就是用abs這個變數指向求絕對值的函式。如果把abs變數付給a變數,那麼,就可以用a()去求絕對值,同時仍然可以用abs求絕對值(因為之前賦給a只是用a變數指向abs,並沒有動abs變數的指向。如果把abs=10那麼,abs就不能再用了,要想再用的話,就要重啟python.

a=abs a(-3) 3

abs(-3) 3

abs=10 abs(-4) TypeError: 'int' object is not callable

既然變數可以接收函式,而函式可以接受變數作為引數,所以函式就可以接受一個函式作為引數,這樣就定義了高階函式

def add(x, y, f):

return f(x) + f(y)

add(3,-4,abs)

5.1.1 map和reduce函式:

map,格式是map(fn,Itrable),就是把itrable裡的元素,依次帶入fn最後得出的是itrator,

def fn():

>>> def fn(x):

... y=x*x

... return y

...

>>> g=map(fn,[1,3,4])

>>> next(g)

1

>>> next(g)

9

如果想要全部顯示出來的話用list生成一個list

即把g=map(fn,[1,3,4])改為list(map(fn,[1,3,4]

reduce:把一個函式作用於一個序列上,(要做用的函式必須接收兩個引數),reduce把計算的結果繼續和序列的下一個元素累計計算。

即公式reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

把str轉化為int,例如

def digit(s):
digit={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}

return digit[s]
def multi(x,y):
result=x*10+y
return result
from functools import reduce
s='13568'
print(reduce(multi,map(digit,s)))

13568

現在改為更簡單的只是定義一個函式,然後把整個的過程定義進去,這樣以後直接就可以呼叫函式就行了

from functools import reduce
digit={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
def strint(r):
def quzheng(r):
return digit[r]
def mulit(x,y):
return x*10+y
return reduce(mulit,map(quzheng,r))
print(strint('453'))

編寫一個prod()函式,可以接受一個list並利用reduce()求積:

from functools import reduce
def prod(L):
def multi(x,y):
return x*y
return reduce(multi,L)
print('3*5*7*9=',prod([3,5,7,9]))

利用mapreduce編寫一個str2float函式,把字串'123.456'轉換成浮點數123.456

def str2float(s):
from functools import reduce
position=len(s)-s.find('.')-1#求出小數點的位置
r=s.replace('.','')#替換小數點
def qiuint(r):
return map(int,r)#吧每個字元變成整數
def qiufloat(a,b):
return a*10+b#把全部字符合成整數
return reduce(qiufloat,map(int,r))/10**position#把整數除以之前的小數點的位置
print(str2float('12343245.65656'))

5.1.2 fiiter定義:把一個函式依次作用在interable的元素上,如果得到的是Ture(意思是,把元素代入fn函式,看得到的結果,這也就意味著fn裡面要有判斷真假的語句,並且返回結果也要有Ture,False),結果保留,如果是false,結果不保留。。形式filter(fn,iterable),(fn是要作用在iterable的函

回數是指從左向右讀和從右向左讀都是一樣的數,例如12321909。請利用filter()篩選出回數:

def is_palindrome(n):
a=n//100
b=n%100
c=b//10
d=b%10
if n<10 or a==d or n>=10 and n<100 and c==d:#判斷條件
return True
output=filter(is_palindrome,range(1,1000))
print('1~1000=',list(output))

自己做的並不完善,當是四位數的時候就沒法判斷了,大致是這個思想:因為filter主要是用fn去作用在每個元素上所以編寫fn的判斷條件是主要的·如果滿足條件返回值就是Ture,否則false,當編寫的時候就以一個元素去編寫較為方便。。

再額外補充兩個人家大神的思路

def is_palindrome(n):
p = True
s = str(n)
l = int(len(s) / 2)
for x in range(l):
if s[x]!=s[-(x + 1)]:
return False
return p

(兩個知識點,第六行用的是不等於,是把首尾不相同的數給排除出來,但是為什麼不把不等於改成等於,直接返回Ture豈不更好,原來如果直按照以上設想,只能把兩位和三位數數出來,但是個位數沒法輸出。。因為個位的時候,range(0)=[],無法參與運算,所以返回保留的只有兩位和三位數,所以這裡是用不等於把兩位和三位數首尾不相同的排除出來,然後把剩下的return為Ture,這樣就把各位的數給保留了

另一個大神的思路

def is_palindrome(n):

r = str(n)

return r == r[::-1]

r[::-1],重新把r首尾相調。。。(不得不感嘆一句,這腦回路真牛逼))

5.1.3 sorted函式,當只有一個變數是,可以對變數進行從小到大排序,同時也是個高階函式,可以接受一個引數和一個key引導函式,工作時就是把函式依次作用於引數上,然後按照作用的結果按照順序進行排序(這裡的排序是對原引數進行排序,得到結果也是原來的引數,按照從小到大組成的序列

l=[64,32,-14,-34,78]

>>> sorted(l)

[-34, -14, 32, 64, 78]

>>> sorted(l,key=abs)

[-14, 32, -34, 64, 78](此時,就是把abs作用在原l上,即[64,32,14,34,78],然後把abs過的結果,按照從小到大排序即[14,32,34,64,78],然後再把此時的順序對應到沒有函式過的元素上,即14對應-14,32對應32,34對應-34,以此類推

例題:假設我們用一組tuple表示學生名字和成績:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

請用sorted()對上述列表分別按名字排序:

再按成績從高到低排序:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

def by_name(t):
return t[0]
L2=sorted(L,key=by_name)
print(L2)

[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]

首先要理解,這裡的key引導的函式是作用在每個元素上,而此例中每個元素就是一個tuple,所以只需寫一個函式把元素裡的字串取出來,然後通過sorted把字串進行排序就行

同理,本例按照數字進行排列,只需取出數字,但是預設的排列順序是從小到大,所以用reserve=true,來反轉順序,也可以return -t[1],通過改變函式來實現

def by_score(t):
return t[1]
L2=sorted(L,key=by_score,reverse=True)
print(L2)

[('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]

5.2 返回函式:定義是一個函式可以接受其他函式作為自己的返回return值,,目的是此刻並不需要用到,當後續需用到被返回的函式的時候,使用返回函式來調取出來,見下例

def deley_sum(args):
def sum():
an=0
for x in range(1,args):
an=an+x
return an
return sum
f=deley_sum(4)#呼叫返回函式,也就是把sum作為返回值,賦給f,此時的f即繼承了sum的運演算法則
print(f())#此時的f後的引數要與sum保持一致

被返回函式是sum也就是目前不想用到,後續想用到的時候就可以呼叫deley_sum,來算出結果。也就是比如現在寫了一個求和的函式sum,但是呢,現在不想用,以後再用,這時就可以在原有的基礎上,定義一個函式,把sum作為這個函式的返回值,日後呼叫這個函式的時候,就直接返回了sum函式。

閉包:即返回函式裡的變數和殘數,可以被被返回函式所使用,當返回被返回函式是,相關變數和引數都儲存在被返回函式中了,如本例中的引數args

返回閉包時牢記一點:返回函式不要引用任何迴圈變數,或者後續會發生變化的變數。

如果一定要引用迴圈變數怎麼辦?方法是再建立一個函式,用該函式的引數繫結迴圈變數當前的值,無論該迴圈變數後續如何更改,已繫結到函式引數的值不變:

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被執行,因此i的當前值被傳入f()
    return fs

我的個媽呀!!!!!!太難了吧。。先複製人家的。。。。以後再慢慢的啃!!!

python中的global和nonlocal - 莫談國是 - SegmentFault 思否​segmentfault.com 1e81d036997633916524889cbbd089ae.png

# 1. 如果使用生成器,沒有什麼問題,按照生成器的做法來呼叫next()即可

# 2. 如果使用閉包知識,且使用變數n(int物件),需要了解的是變數的作用域遵循LEGB規則,然後在counter()函式內宣告nonlocal n

# 3. 如果使用閉包知識,且使用變數n(list物件),除了要理解LEGB規則外,還要明白python在函式內可以直接讀取其他作用域範圍的變數,但是修改變數時就會預設視為區域性變數;在這種情況下n是變數名,我們使用的是n對應list物件(可變物件)的內容,變數n未被修改過,因此使用時不需要對n做nonlocal宣告即可完成練習。