一、背景
在學習函數之前,一直遵循:面向過程編程,即:根據業務邏輯從上到下實現功能,其往往用一長段代碼來實現指定功能,開發過程中最常見的操作就是粘貼複製,也就是將之前實現的代碼塊複製到現需功能處,如下:
while True:
if cpu利用率 > 90%:
#發送郵件提醒
連接郵箱服務器
發送郵件
關閉連接
if 硬盤使用空間 > 90%:
#發送郵件提醒
連接郵箱服務器
發送郵件
關閉連接
if 內存佔用 > 80%:
#發送郵件提醒
連接郵箱服務器
發送郵件
關閉連接
腚眼一看上述代碼,if條件語句下的內容可以被提取出來公用,如下:
def 發送郵件(內容)
#發送郵件提醒
連接郵箱服務器
發送郵件
關閉連接
while True:
if cpu利用率 > 90%:
發送郵件('CPU報警')
if 硬盤使用空間 > 90%:
發送郵件('硬盤報警')
對於上述的兩種實現方式,第二次必然比第一次的重用性和可讀性要好,其實這就是函數式編程和麪向過程編程的區別:
- 函數式:將某功能代碼封裝到函數中,日後便無需重複編寫,僅調用函數即可
- 面向對象:對函數進行分類和封裝,讓開發“更快更好更強...”
函數式編程最重要的是增強代碼的重用性和可讀性
二、定義和使用
def 函數名(參數):
...
函數體
...
返回值
函數的定義主要有如下要點:
- def:表示函數的關鍵字
- 函數名:函數的名稱,日後根據函數名調用函數
- 函數體:函數中進行一系列的邏輯計算,如:發送郵件、計算出 [11,22,38,888,2]中的最大數等...
- 參數:爲函數體提供數據
- 返回值:當函數執行完畢後,可以給調用者返回數據。
1. 返回值
函數是一個功能塊,該功能到底執行成功與否,需要通過返回值來告知調用者。
以上要點中,比較重要有參數和返回值:
def 發送短信():
發送短信的代碼...
if 發送成功:
return True
else:
return False
while True:
# 每次執行發送短信函數,都會將返回值自動賦值給result
# 之後,可以根據result來寫日誌,或重發等操作
result = 發送短信()
if result == False:
記錄日誌,短信發送失敗..
2、參數
- 普通參數
- 默認參數
- 動態參數
普通參數
# ######### 定義函數 #########
# name 叫做函數func的形式參數,簡稱:形參
def func(name):
print(name)
# ######### 執行函數 #########
# 'wupeiqi' 叫做函數func的實際參數,簡稱:實參
func('wupeiqi')
默認參數
def func(name, age = 18):
print( "%s:%s" %(name,age))
# 指定參數
func('wupeiqi', 19)
# 使用默認參數
func('alex')
注:默認參數需要放在參數列表最後
動態參數
def func(*args):
print(args)
# 執行方式一
func(11,33,4,4454,5)
# 執行方式二
li = [11,2,2,3,3,4,54]
func(*li)
def func(**kwargs):
print(args)
# 執行方式一
func(name='wupeiqi',age=18)
# 執行方式二
li = {'name':'wupeiqi', age:18, 'gender':'male'}
func(**li)
def func(*args, **kwargs):
print(args)
print(kwargs)
三、局部變量和全局變量
在子程序中定義的變量稱爲局部變量,在程序的一開始定義的變量稱爲全局變量。
全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。
當全局變量與局部變量同名時:
在定義局部變量的子程序內,局部變量起作用;在其它地方全局變量起作用。
name='lhf'
def change_name():
print('我的名字',name)
change_name()
def change_name():
name='帥了一筆'
print('我的名字',name)
change_name()
print(name)
def change_name():
global name
name='帥了一筆'
print('我的名字',name)
change_name()
print(name)
四、遞歸調用
在函數內部,可以調用其他函數。如果在調用一個函數的過程中直接或間接調用自身本身
def calc(n):
print(n)
if int(n/2) ==0:
return n
return calc(int(n/2))
calc(10)
輸出:
10
5
2
1
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import time
person_list=['alex','wupeiqi','yuanhao','linhaifeng']
def ask_way(person_list):
print('-'*60)
if len(person_list) == 0:
return '沒人知道'
person=person_list.pop(0)
if person == 'linhaifeng':
return '%s說:我知道,老男孩就在沙河匯德商廈,下地鐵就是' %person
print('hi 美男[%s],敢問路在何方' %person)
print('%s回答道:我不知道,但念你慧眼識豬,你等着,我幫你問問%s...' %(person,person_list))
time.sleep(3)
res=ask_way(person_list)
# print('%s問的結果是: %res' %(person,res))
return res
res=ask_way(person_list)
print(res)
遞歸問路
遞歸特性:
-
必須有一個明確的結束條件
-
每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
- 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)
五、匿名函數
匿名函數就是不需要顯式的指定函數
#這段代碼
def calc(n):
return n**n
print(calc(10))
#換成匿名函數
calc = lambda n:n**n
print(calc(10))
匿名函數主要是和其它函數搭配使用的呢,如下
l=[3,2,100,999,213,1111,31121,333]
print(max(l))
dic={'k1':10,'k2':100,'k3':30}
print(max(dic))
print(dic[max(dic,key=lambda k:dic[k])])
res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:
print(i)
輸出
1
25
49
16
64
六、內置函數
- map
array=[1,3,4,71,2]
ret=[]
for i in array:
ret.append(i**2)
print(ret)
#如果我們有一萬個列表,那麼你只能把上面的邏輯定義成函數
def map_test(array):
ret=[]
for i in array:
ret.append(i**2)
return ret
print(map_test(array))
#如果我們的需求變了,不是把列表中每個元素都平方,還有加1,減一,那麼可以這樣
def add_num(x):
return x+1
def map_test(func,array):
ret=[]
for i in array:
ret.append(func(i))
return ret
print(map_test(add_num,array))
#可以使用匿名函數
print(map_test(lambda x:x-1,array))
#上面就是map函數的功能,map得到的結果是可迭代對象
print(map(lambda x:x-1,range(5)))
map函數
- filter
#電影院聚集了一羣看電影bb的sb,讓我們找出他們
movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']
def tell_sb(x):
return x.startswith('sb')
def filter_test(func,array):
ret=[]
for i in array:
if func(i):
ret.append(i)
return ret
print(filter_test(tell_sb,movie_people))
#函數filter,返回可迭代對象
print(filter(lambda x:x.startswith('sb'),movie_people))
--------------
name_dic=[
{'name':'alex','age':1000},
{'name':'wupeiqi','age':10000},
{'name':'yuanhao','age':9000},
{'name':'linhaifeng','age':18},
]
res = filter(lambda x:x['age'] <= 18,name_dic)
print(list(res))
filter函數
3.reduce
l = [1,2,3,100]
def gn(x,y):
return x*y
def reduce_test(sd,lis,init=None):
if init is None:
res = lis.pop(0)
else:
res = init
for i in lis:
res = sd(res,i)
return res
print(reduce_test(gn,l,100))
------------------------
from functools import reduce
res = reduce(lambda x,y:x+y,l,100)
print(res)
總結:
- map:理序列中的每個元素,得到的結果是一個‘列表’,該‘列表’元素個數及位置與原來一樣
- filter遍歷序列中的每個元素,判斷每個元素得到布爾值,如果是True則留下來
- reduce:處理一個序列,然後把序列進行合併操作
# print(abs(1)) #絕對值
# print(all([1,23,''])) #是否都爲真
# print(all('')) #爲真
# print(any([1,3,''])) #只要有一個爲真,即爲真
# print(bin(10))#10進制->2進制
# print(hex(12))#10進制->16進制
# print(oct(12))#10進制->8進制
#空、NONE、0、的布爾值爲false,其餘都爲true
# print(bool(''))
# name = '你好'
# print(bytes(name,encoding='utf-8')) #轉換爲字節,並指定字符編碼格式
# print(bytes(name,encoding='utf-8').decode('utf-8'))
# print(divmod(10,3)) #做除法,顯示商和餘數,可用於分頁判斷
#可hash的數據類型即不可變數據類型,不可hash的數據類型即可變數據類型
# name = 'lingxd'
# print(hash(name))
# print(hash(name))
#
# print(help(all))
# print(isinstance(1,int)) #判斷 數據類型是否正確
# print(isinstance(1,str))
# print(globals()) #全局變量
# print(locals()) #局部變量
# l = [1,2,34]
# print(max(l)) #輸出最大值
# print(min(l)) #輸出最小值
# print(list(zip(('a','b','c'),(1,2,3))))
#
# p = {'name':'lingxd','age':25,'gender':'man'}
# print(list(zip((p.keys()),(p.values()))))
#
# print(list(zip((['a','b']),('12345'))))
# l={'alex_age':18,'wupei_age':20,'zsc_age':100,'lhf_age':30}
#
# print(max(zip((l.values()),(l.keys()))))
# people=[
# {'name':'alex','age':1000},
# {'name':'wupei','age':10000},
# {'name':'yuanhao','age':9000},
# {'name':'linhaifeng','age':18},
# ]
#
# print(max(people,key=lambda dic:dic['age']))
# print(chr(97)) #轉換爲字符編碼
# print(ord('a')) #反轉字符編碼
#
# l = [1,2,3,4,5]
# print(list(reversed(l))) #反轉,不會修改原數據
#
# print(pow(3,2)) #相當於3**2
# print(pow(3,2,2)) #相當於3**2 %2取餘數
# print(round(3.6)) #四捨五入
#
# l = 'lingxd'
# s1 = slice(1,3) #相當於切片操作,定義切片
# print(l[s1])
# l = [3,2,5,9,11]
# print(sorted(l)) #排序,從小到大
#
# people=[
# {'name':'alex','age':1000},
# {'name':'wupei','age':10000},
# {'name':'yuanhao','age':9000},
# {'name':'linhaifeng','age':18},
# ]
#
# print(sorted(people,key=lambda dic:dic['age']))
# name_dic={
# 'abyuanhao': 11900,
# 'alex':1200,
# 'wupei':300,
# }
#
# print(sorted(zip((name_dic.values()),(name_dic.keys()))))
# l=[1,2,3,4]
# print(sum(l)) #求和
# print(sum(range(5)))
# print('123',type('123')) #顯示類型
# s = '123'
# if type(s) is str:
# s = int(s)
# res = s+1
# print(res)
# def heh():
# s = 'heheh'
# print(locals())
# print(vars())
#
# heh()
#
# print(vars(type))