Python開發【第三篇】:Python基礎之函數

一、背景

在學習函數之前,一直遵循:面向過程編程,即:根據業務邏輯從上到下實現功能,其往往用一長段代碼來實現指定功能,開發過程中最常見的操作就是粘貼複製,也就是將之前實現的代碼塊複製到現需功能處,如下:

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)

遞歸問路

遞歸特性:

  1. 必須有一個明確的結束條件

  2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少

  3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(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

六、內置函數

  1. 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函數
  1. 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))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章