Python基礎知識-09-函數

 

python其餘知識目錄html

一、函數介紹

函數是組織好的,可重複使用的,用來實現單一,或相關聯功能的代碼段。
函數能提升應用的模塊性,和代碼的重複利用率。你已經知道Python提供了許多內建函數,好比print()
。但你也能夠本身建立函數,這被叫作用戶自定義函數。python

def 函數名(參數列表):
     函數體d
函數名(參數)
函數名(參數)

二、函數使用優缺點:

公司隨隨便便幾百上千行。可讀性,重用性,函數,面向過程編程
優勢:
缺點:
面向過程,能夠將可重複性的代碼作成一個函數,用參數代替變化的量,實現具備重複性操做的功能。
當事物須要作這個操做的時候,調用函數便可實現功能。#本身理解
#發郵件:設置裏面開啓pop3,smtp服務器 ,往smtp服務器發郵件
好比發郵件,不少對象都使用的一個動做,寫成函數,調用函數。避免代碼冗餘。
什麼狀況寫函數,就是爲了能重複使用某個功能,就寫成函數,一個功能一個函數。或者是爲了方便閱讀,增長代碼可讀性
函數式編程是作什麼的?避免重複性代碼。代碼拆分,加強可移植性,可讀性

本質:將N行代碼拿到別處並給他起個名字,之後經過名字就能夠找到這段代碼並執行。
場景:代碼重複執行。
代碼量特別多超過一屏,能夠選擇經過函數進行代碼的分割。shell

三、函數定義:

你能夠定義一個由本身想要功能的函數,如下是簡單的規則:
函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。
任何傳入參數和自變量必須放在圓括號中間,圓括號之間能夠用於定義參數。
函數的第一行語句能夠選擇性地使用文檔字符串—用於存放函數說明。
函數內容以冒號起始,而且縮進。
return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return至關於返回 None

語法:
Python 定義函數使用 def 關鍵字,通常格式以下:express

def 函數名(參數列表):
    函數體

默認狀況下,參數值和參數名稱是按函數聲明中定義的順序匹配起來的。編程

函數執行:
def xiaoma():
print("魔降風雲變")
xiaoma()
---------結果:
魔降風雲變

四、函數調用

定義一個函數:給了函數一個名稱,指定了函數裏包含的參數,和代碼塊結構。服務器

這個函數的基本結構完成之後,你能夠經過另外一個函數調用執行,也能夠直接從 Python 命令提示符執
行。
函數不調用,內部代碼不執行。調用後用不用變量接收返回值,函數都會執行。閉包

def xiaoma():
    print("魔降風雲變")
xiaoma()
---------結果:
魔降風雲變

def xiaoma():
    print("魔降風雲變")
a=xiaoma()
----------結果:
魔降風雲變

def xiaoma():
print("魔降風雲變")

def mcw():        #函數調用函數
print("我是:")
xiaoma()
mcw()
--------------結果:
我是:
魔降風雲變

五、函數傳參

5.一、函數傳參簡介

不一樣的對象作相同的操做,能夠定義函數。若是每一個對象還有些區別,那麼有區別的地方使用函數傳參

定義帶參數的函數的時候
函數式編程。經過傳參,返回不一樣的值,返回不一樣的參數。同一個功能不一樣的地方就使用傳參
形式參數(形參):形參就是形式上的參數,能夠理解爲數學的X,沒有實際的值,經過別人賦值後纔有
意義。至關於變量。
實際參數(實參):實參就是實際意義上的參數,是一個實際存在的參數,能夠是字符串或是數字等app

函數裏面使用字符串格式化
函數能夠定死了,也能夠傳遞變量。寫函數不必定須要參數。若是有變的,使用參數,沒有變的就定死
了就能夠,看實際狀況了。less

 
 
def eat(arg1,arg2):
print("%s喜歡吃%s"%(arg1,arg2))
eat("小馬過河","米飯")
eat("小明","麪條")
-----------結果:

小馬過河喜歡吃米飯
小明喜歡吃麪條dom

5.1沒有函數傳參
案例1:
使用函數只計算某一個列表內元素的和:
def list_sum():
    li = [1, 2, 3]
    sum=0
    for i in li:
        sum+=i
    print(sum)
list_sum()
-----------結果
6

5.2一個函數傳參:
案例2:
使用函數計算指定列表內元素的和:
def list_sum(li):
    sum=0
    for i in li:
        sum+=i
    print(sum)
info=[1,2,3]
list_sum(info)
-------------結果:
6

報錯問題1:
報錯:函數沒有形參,調用函數時帶着參數的報錯:
def list_sum():
    sum=0
    for i in li:
        sum+=i
    print(sum)
info=[1,2,3]
list_sum(info)      #調用時,能夠直接作參數,也能夠用變量作實參
-------------------結果:
list_sum(info)
TypeError: list_sum() takes 0 positional arguments but 1 was given

5.3多個函數傳參:
def xiaoma(arg1,arg2):
    print(arg1+arg2)
xiaoma(2,3)
-----------結果:
5

報錯問題2:傳參傳少了
def xiaoma(arg1,arg2):
    print(arg1+arg2)
xiaoma(2)
-----------結果:
    xiaoma(2)
TypeError: xiaoma() missing 1 required positional argument: 'arg2'

報錯問題3:傳參傳多了
def xiaoma(arg1,arg2):
    print(arg1+arg2)
xiaoma(2,3,4)
------------結果:
  xiaoma(2,3,4)
TypeError: xiaoma() takes 2 positional arguments but 3 were given

嚴格按照順序來傳參數,按位置一一對應。

5.2基本參數知識

  • 任意個數
  • 任意類型
def func(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8):
    print(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
func(1,False,None,"mcw",["xiaoma","1"],(1,2),{"name":"xiaoma"},{3,4})
------結果:
1 False None mcw ['xiaoma', '1'] (1, 2) {'name': 'xiaoma'} {3, 4}

 5.三、位置傳參(調用函數並傳入參數)【執行】

位置傳參:根據位置意義對應傳遞參數

def func(a1, a2):
    print(a1, a2)
func(1, 3)
------------結果:
1 3

5.4關鍵字傳參【執行】

關鍵字傳參:指定形參接收實參

def func(a1, a2, a3):
    print(a1, a2, a3)
func(1,2,a3=9)          
func(1,a2=2,a3=9)
func(a1=1,a2=2,a3=9)
------------------結果:
1 2 9
1 2 9
1 2 9

def func(a1, a2, a3):
    print(a1, a2, a3)
func(a1=1,2,3) # 錯誤
-------------結果:
SyntaxError: positional argument follows keyword argument
follows關鍵字定位論點論據

5.5默認參數【定義】

使用場景:定義函數默認參數,方便

指定形參等於什麼參數,若是沒有接收到實參,那麼函數就使用默認參數

def func(a1,a2,a3=9,a4=10):      #a3默認9,a4默認10,調用時能夠傳能夠不傳。;給默認傳參傳了參數就用傳進函數的參數,不然用的默認參數。好比open函數有默認的參數。
print(a1,a2,a3,a4)
func(11,22)
func(11,22,10)
func(11,22,10,100)
func(11,22,10,a4=100)
func(11,22,a3=10,a4=100)
func(11,a2=22,a3=10,a4=100)
func(a1=11,a2=22,a3=10,a4=100)
-------------------結果:
11 22 9 10
11 22 10 10
11 22 10 100
11 22 10 100
11 22 10 100
11 22 10 100
11 22 10 100

5.6萬能參數(打散)

*args:傳遞多個實參給形參*args,並讓函數以元組的形式來接收外部傳參

        -  實參前面加*號,將實參內的每一個元素傳到*args元組中,而非實參自己。

*kwargs:傳遞多個鍵值對或字典給*kwargs,而且在函數內以字典的形式存在

         -  實參字典前面加**給*kwargs,會將實參內每一個鍵值對添加到*kwargs字典中,而非實參字典自己

  • *args

    • 能夠接受任意個數的位置參數,並將參數轉換成元組。

    • *args只能接收n個參數。傳入多個實參時,都放到args這個元組裏面。若是傳入元組參數,那麼元組做爲args的單個元素。若是*(),實參元組前面有*,那麼實參元組內的每一個元素都放到形參構成的元組內,即形參

    • 構成的元組內是實參內的各個元素。只能位置傳參,不能關鍵字傳參#假設能夠關鍵字傳參,那麼設定以後,它後面就接收不了參數 

    • 了,因此不能夠作關鍵字傳參

    • 使用場景:不肯定須要傳參個數的時候使用萬能參數。

      • 調用函數無 *

        def func(*args):
            print(args)       #*args只能接收n個參數。傳入多個實參時,都放到args這個元組裏面。
        func(1,2,3,4)
        -------------------結果:
        (1, 2, 3, 4)
        def func(*args):
        print(args) #若是傳入元組參數,那麼元組做爲args的單個元素。
        func((1,2),(3,4))
      • 調用函數有 *

        def func(*args):
            print(args)
        func(*(1,2,3,4))         #若是*(),實參元組前面有*,那麼實參元組內的每一個元素都放到形參構成的元組內,即形參
        func(*[1,2,3,4])
        -----------------------結果:
        (1, 2, 3, 4)
        (1, 2, 3, 4)

        def func(*args):  #函數內print星號和不print星號的區別
        print(args)
        print(*args)
        func(1,2,3,4)
        ---------結果:

        (1, 2, 3, 4)
        1 2 3 4

    • 只能用位置傳參

      def func(*args):
          print(args)
      func(1)
      func(1,2) # args=(1, 2)
      func((11,22,33,44,55)) # args=((11,22,33,44,55),)
      func(*(11,22,33,44,55)) # args=(11,22,33,44,55)
      -----------------------結果:
      (1,)
      (1, 2)
      ((11, 22, 33, 44, 55),)
      (11, 22, 33, 44, 55)
  • **kwargs

    • 能夠接受任意個數的關鍵字參數,並將參數轉換成字典。

      • 調用函數無 **

        def func(**kwargs):
            print(kwargs)
        func(k1=1,k2="mcw")
        ------------------------結果:
        {'k1': 1, 'k2': 'mcw'}
      • 調用函數有**

        def func(**kwargs):
            print(kwargs)
        func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'}
        ---------------------------------結果:
        {'k1': 'v2', 'k2': 'v2'}
    • 只能用關鍵字傳參

    • 綜合應用:無敵 + 無敵 => 真無敵

      def func(*args,**kwargs):
          print(args,kwargs)
      func(1,2,3,4,5,k1=2,k5=9,k19=999)
      func(*[1,2,3],k1=2,k5=9,k19=999)
      func(*[1,2,3],**{'k1':1,'k2':3})
      func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3})
      ------------------------結果:
      (1, 2, 3, 4, 5) {'k1': 2, 'k5': 9, 'k19': 999}
      (1, 2, 3) {'k1': 2, 'k5': 9, 'k19': 999}
      (1, 2, 3) {'k1': 1, 'k2': 3}
      (111, 222, 1, 2, 3) {'k11': 'alex', 'k1': 1, 'k2': 3}

5.七、混合傳參

def func(a1,*args)
func(1,2,3) 傳了1給a1,後面給args

def func(a1,*args,a2) 混搭
func(1,2,3,a2=4)

def func(a1,*args,a2=10) 混搭 a2只能靠關鍵字來傳與上同。
func(1,2,3,a2=4)

def func(a1=2,*args,a2) #混搭 錯誤方式
func(1,2,3,a2=4)

def func(**kwargs) #傳多個鍵值對到函數,實參爲鍵=值 #萬能,傳n個關鍵字參數。並將參數轉換
爲字典
func(k1=1,k2="s")

def func(**kwargs): #kwargs={k1=1,k2="s"} #傳字典到函數內 **字典
print(kwargs)
func(**{"k1":1,"k2":"s"})
-------------結果:
{'k1': 1, 'k2': 's'}

def func(**kwargs) #kwargs={k1:{"m":"c"},k2:"s"} #將鍵值對和字典一塊兒傳到函數內,
func(k1={"m":"c"},k2="s")

5.八、傳參使用場景總結:

  一、我想要簡單點的基本傳參,用位置傳參;
  二、我傳參想讓誰接收,用關鍵字傳參。               
  三、我沒傳參想讓形參有個默認值,用默認傳參;
  四、我要傳遞多個參數,用一個*號的接收;
  五、我要傳遞多個鍵值對或字典,用兩個**接收。

函數:增長代碼重用性,可讀性。
好比去樓下拿快遞,是個函數,告訴他拿**的快遞,他就拿到**的快遞

六、函數返回值return

1) print 和 return 的區別,print 僅僅是打印在控制檯,而 return 則是將 return 後面的部分做
爲返回值做爲函數的輸出,能夠用變量接走,繼續使用該返回值作其它事。
2)函數須要先定義後調用,函數體中 return 語句的結果就是返回值。若是一個函數沒有 reutrn 語句
,其實它有一個隱含的 return 語句,返回值是 None,類型也是 'NoneType'。
3)return做用:結束函數調用、返回值
4)終止函數的方法:知足某個條件 return False

成功與不成功返回一個結果。若是不須要打印,用戶只須要某個結果,那麼讓函數返回一個值,讓用戶
根據返回值作對應的操做。return實現函數返回值。
調用函數,並用變量接收函數的返回值。

6.1使用變量接收返回值:

def xiaoma():
    a=1
    return a
mcw=xiaoma()
print(mcw)
------------結果
1

6.2用戶根據函數返回值作別的操做。(根據返回值進行通訊)

#當小明吃完飯,給我返回1。小明吃完後小馬過河找他玩

def xiaoming(arg):
    a=0
    if arg=="吃完":
        a=1
    return a
status=xiaoming("吃完")
if status==1:
    print("小馬過河去找小明玩")
--------------結果:
小馬過河去找小明玩

6.3返回多個值的方法:

若是程序須要有多個返回值,則既可將多個值包裝成列表以後返回,也可直接返回多個值。若是 Python
函數直接返回多個值,Python 會自動將多個返回值封裝成元組。多個值用逗號隔開。

1)python 函數使用 return 語句返回 "返回值",能夠將其賦給其它變量做其它的用處

2)全部函數都有返回值,若是沒有 return 語句,會隱式地調用 return None 做爲返回值

3)一個函數能夠存在多條 return 語句,但只有一條能夠被執行,若是沒有一條 reutrn 語句被執行,一樣會隱式調用 return None 做爲返回值

4)若是有必要,能夠顯式調用 return None 明確返回一個None(空值對象)做爲返回值,能夠簡寫爲 return

5)若是函數執行了 return 語句,函數會馬上返回,結束調用,return 以後的其它語句都不會被執行了

def list_sum(li):
    sum=0
    e_str=""
    for i in li:
        e_str+=str(i)
        sum+=i
    return sum,e_str
li=[1,2,3]
mcw=list_sum(li)  # 獲取list_sum函數返回的多個值,多個返回值被封裝成元組
v1,v2=list_sum(li)               #此外,也可以使用 Python 提供的序列解包功能,直接使用多個變量接收函數返回的多個值。
print(mcw)
print(v1,v2)
---------------結果:
(6, '123')
6 123

6.4return終止循環

def mcw():       #沒有return的時候,返回值默認是None,循環正常結束。
    for i in range(1,4):
        print(i)
m=mcw()
print(m)
-------------結果:
1
2
3
None

def mcw():    #有return的時候,返回指定的值,並終止函數向後繼續執行了。
    for i in range(1,4):
        if i==3:
            return "終止函數了"
        print(i)
m=mcw()
print(m)
-------------結果:
1
2
終止函數了

6.五、直接打印返回值

def mcw():
    return "魔降風雲變"
print(mcw())

6.6 for .. else .. 語句 (意外終止狀況)

# 表示若是 for 語句段的內容正常循環結果纔會執行 else 段的語句,若是 for 在循環過程當中時被 break 或者 return 語句意外終止循環,就不會執行 else 段中的語句。

6.七、return能夠返回任意類型。

#假如須要函數返回字典,列表等,就能夠給函數調用的時候使用。

retrue 一個數據類型。

def func(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8):
return (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
print(func(1,False,None,"mcw",["xiaoma","1"],(1,2),{"name":"xiaoma"},{3,4}))
-------------------結果:
(1, False, None, 'mcw', ['xiaoma', '1'], (1, 2), {'name': 'xiaoma'}, {3, 4})

6.八、if判斷使用返回值的三種方式:

def func(a1,a2):
    if a1>a2:
        return a1
    else:
        return a2
def func(a1,a2):
    return a1 if a1>a2 else a2
def func(a1,a2):
    b=a1 if a1>a2 else a2
    return b

 6.9可利用返回值True和默認的返回值None作函數返回的判斷

def func(arg1):
    if arg1==1:
        return True
print(func(0))
-----------結果:
None

6.10其餘的返回值,非函數返回值總結

li=[1,2]
print(li.append(3))      #沒有返回值就是None嗎?
---------------結果:
None

li=[1,2]
m=li.append(3)               
print(m)
-----------結果:
None

a="mcw"
a="*".join(a)
print(a)
----------------結果:
m*c*w

總結:列表全部方法基本上都是返回None,字符串的全部方法基本上是返回新值

七、函數做用域

7.1全局做用域

  • py文件:全局做用域

  • 函數:局部做用域

  • 變量先建立才能再使用。
  • 函數也能夠看作一個變量,指向一堆代碼
  • 做用域中的數據歸本身全部,別人訪問不到,局部做用域能夠繼承全局做用域 
  • 函數調用全局變量,可使用在函數調用以前的環境變量,可是不可使用函數調用以後的
  • print(func) 返回的地址
    print(func()) 返回調用值

  • a = 1
    def s1():
        x1 = 666
        print(x1)
        print(a)
        print(b)
    
    b = 2
    print(a)
    s1()
    a = 88888
    def s2():
        print(a,b)
        s1()
    
    s2()
    ---------------------結果:
    1
    666
    1
    2
    88888 2
    666
    88888
    2
     
  • 總結:

    • 一個函數一個做用域,(其餘語言不少是一個代碼塊一個做用域

    • 做用域中查找數據的規則,優先在本身做用域尋找,本身沒有就去父集做用域中尋找,父集沒有再不斷往上層的父集去找。直到全局做用域,再沒有就報錯。

    • 父集沒法使用子集的變量。子集能夠不斷往外層的父集尋找變量
    • 一、找變量,本層沒有,二、去上一級做用域中,找調用本函數以前最後賦值的那個變量,三、若是到達全局環境變量後尚未就會報錯。若是沒有到達環境變量,請執行第2步。
    • globla 找到全局   找到後能夠給全局變量從新賦值,
      nonloacl 找到上級,找到後能夠給上級變量從新賦值。

    • 做用域每層都是有本身獨立的內部空間的,子能繼承父,但不能從新賦值父,須要藉助global和nonlocal。#思考(不肯定的問題):有global和nonlocal找到父所在空間,從新開闢空間進行賦值,不然開闢的是本身所在的空間嗎?

    • def func():
          x = 9
          print(x)
      func()
      print(x)         #函數內部能使用內部變量,可是函數外部不能使用函數內部變量
      -------------結果:
      9
      Traceback (most recent call last):
        File "D:/aPython_full目錄/小馬過河的代碼練習/mcwday09.py", line 269, in <module>
          print(x)
      NameError: name 'x' is not defined

 

做用域中查找數據規則:優先在本身的做用域找數據,本身沒有就去 "父級" -> "父級" -> 直到全局,所有麼有就報錯。注意:父級做用域中的值究竟是什麼?

x = 10
def func():
    x = 9
    print(x)
func()
---------------結果:
9

globla 找到全局 找到後能夠從新賦值,
nonloacl 找到上級,找到後後面從新賦值
函數能修改函數外部可變數據類型如列表,集合,字典,可是默認是沒法從新賦值的。
若是必定要在函數中給環境變量從新賦值,使用gloabal 變量。子做用域從新賦值全局變量
若是是子函數中使用global從新賦值,改的也是全局
nonloacl改的是父集,上一層的變量。
儘可能不要修改全局。會形成代碼出現問題
全局變量都是使用大寫。局部變量正常的就好了。方便閱讀。潛規則。

7.二、global語句

 https://www.jb51.net/article/147644.htm

https://blog.csdn.net/weixin_37583747/article/details/81262859

7.三、nonlocal語句

 八、lambda函數(匿名函數)

8.一、lambda函數簡介

python 使用 lambda 來建立匿名函數。

所謂匿名,意即再也不使用 def 語句這樣標準的形式定義一個函數。

  • lambda 只是一個表達式,函數體比 def 簡單不少。
  • lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
  • lambda 函數擁有本身的命名空間,且不能訪問本身參數列表以外或全局命名空間裏的參數。
  • 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增長運行效率。

8.二、lambda 函數語法

lambda 函數的語法只包含一個語句,以下:

lambda [arg1 [,arg2,.....argn]]:expression

8.三、

lambda 爲了解決簡單函數的狀況。運算至關於簡單函數編寫方式。這樣函數就至關於一個變量
一行表示,因此不定義變量,使用上一層做用域的變量
變量名=lambda 參數(有無*/**):操做或者函數返回值(返回值可爲表達式,爲三元運算;表達式有返回的就
做爲返回值,不然返回None)

表達式1:
沒有參數,只返回指定值
有一個參數,返回表達式
有*和**的參數,舉例好比返回*和**長度和
lambda 表達式結合三元運算,返回值部分使用三元運算。
多個lambda放入列表。調用lambda.

九、函數中高級使用  高階函數

9.一、函數能夠做爲變量來使用

1
def func():
    print("mcw")
v1 = func  #將函數名賦予一個變量,再給變量加上小括號便能代替原函數名執行這個函數。函數名指

向函數體的內存位置
func()  #
v1()
-------------結果:
mcw
mcw

由上面那個函數打印可知,函數名賦予給變量後,他們都是指向一個內存地址,函數()表明函數返回值

,默認爲None。
print(type(func),type(func()),func,func())
print(type(v1),type(v1()),v1,v1())
------------結果:
123
123
<class 'function'> <class 'NoneType'> <function func at 0x00A28D20> None
123
123
<class 'function'> <class 'NoneType'> <function func at 0x00A28D20> None
2)函數名能夠放入列表等數據類型,調用函數時加上小括號
def func():
    print(123)
func_list = [func, func, func]
func_list[0]()
-----------結果:
123

def func():
    print(123)
func_list = [func, func, func]
for item in func_list:        循環函數列表並打印函數返回值
    v = item()
    print(v)
----------------結果:
123
None
123
None
123
None

3)函數名做爲字典的值來用,(不建議當作鍵來用,沒啥意義)。
def func():
    print(123)
def bar():
    print(666)
info = {'k1': func, 'k2': bar}
info['k1']()
info['k2']()
------------------結果:
123
666

4)容易弄錯的案例:
def func():
    return 123
func_list1 = [func,func,func]
func_list2 = [func(),func(),func()]
print(func_list1)
print(func_list2)
info = {
    'k1':func,
    'k2':func(),
}
print(info)
------------------結果:
[<function func at 0x00648D20>, <function func at 0x00648D20>, <function func at 

0x00648D20>]        #func函數名是指向函數的地址
[123, 123, 123]     # func()是函數返回值。這裏指定返回值爲123
{'k1': <function func at 0x00648D20>, 'k2': 123}  

)綜上可知:
def func():
    print("mcw") v1 = func 
函數名實質上就是函數的內存地址。

當咱們定義a=1的時候,系統會開闢一塊內存空間來保存1,而後用a變量名保存1所在的內存地址引用,變量名就好像C語言中的指針,你們能夠把引用理解成地址,a裏面存的是1這個數值所在的地址,a存了1的引用。當咱們在代碼中定義了一個函數,系統會分配一塊內存空間,用於保存函數體的內部變量和函數名,這個v1只是一個變量名,保存了函數內存中的地址,咱們能夠v1=func,v2=func.這樣的操做就至關於把func中引用的地址,賦值給v1,v2 ,這樣v1和v2都指向了func函數所在的引用,咱們能夠v1()和v2()來
調用func函數,調用其實是一個函數,而v1,v2,func三個變量存了同一個函數的地址。

9.二、函數能夠看成參數進行傳遞

1
def func(arg):
    print(arg)
def show():
    return 999
func(show)
----------結果:
<function show at 0x00598D20>  #將show函數做爲參數傳到func函數,結果爲print(show),show這個

函數名指向內存地址

2
def func(arg):
    v1 = arg()
    print(v1)
def show():
    print(666)
func(show)
---------------結果:
666
None
#函數執行分析:將函數名show做爲func的參數,執行函數後,arg()會讓show函數執行並打印666,而後

將show函數執行的默認返回結果賦予變量v1,打印出v1的值。
3
def func(arg):
    v1 = arg()
    print(v1)
def show():
    print(666)
result = func(show)
print(result)
---------------結果:
666
None
None
#函數執行分析:將函數名show傳參給func函數,而後show會在func內執行,打印666,並將默認返回值

賦予變量v1並打印。func函數執行返回默認值None並將值賦予變量result,而後打印result
4)函數傳參功能的使用案例。
(指定用戶輸入選項,並將每一個選項的功能寫成函數,而後將函數作成字典,根據用戶輸入執行不一樣的函數,實現不一樣的功能) def func(): print(
'花費查詢') def bar(): print('語音溝通') info = { 'f1': func, 'f2': bar, } choice = input('請選擇要選擇功能:') function_name = info.get(choice) if function_name: function_name() else: print('輸入錯誤') ---------------結果: 請選擇要選擇功能:f1 花費查詢

9.三、函數能夠作返回值來使用

1)沒有
def func():
    print(123)
def bar():
    return func
v = bar()
v()
-----------結果:
123
#函數執行分析:函數bar執行後返回另外一個函數名func,將函數名賦值給變量v,v()執行函數就等於func()執行func函數,即打印出123(緣由:賦值後,v和func指向同一個函數)
2)返回另外一個函數名並賦值給變量
name = 'mcw'
def func():
    print(name)
def bar():
    return func
v = bar()
v()
--------------結果:
mcw
#函數執行分析:執行bar函數的返回值(func函數名)賦給變量v。執行v也是執行func函數,打印變量name,func當前做用域沒有變量name,因而去上級做用域中找到並打印出來。
3)返回子函數名並賦值給變量
def bar():
    def inner():
        print(123)
    return inner
v = bar()
v()
----------結果:
123
#函數執行分析:執行bar函數返回inner,並將子函數名賦值給變量v,執行函數v就是執行函數inner,

並打印出123.
4)返回值爲子函數結合做用域
name = 'xiaoma'
def bar():
    name = 'mcw'
    def inner():
        print(name)
    return inner
v = bar()
v()
------------------結果:
mcw
#函數執行分析:執行函數bar,將返回值inner函數名賦值給變量v,調用v即執行inner函數(兩者執行同一個函數)。inner當前做用域沒有變量name,那麼先從上一級做用域中去找。

name = 'mcw'
def bar(name):
    def inner():
        print(name)
    return inner
v1 = bar('yh') # { name=yh, inner }  # 閉包,爲函數建立一塊區域(內部變量供本身使用),爲他

之後執行提供數據。
v2 = bar('syn') # { name=syn, inner }
v1()
v2()
-----------------結果:
yh
syn
#函數執行分析:[1]執行bar函數並傳入參數yh後,系統會建立一個獨立的內存空間給函數bar,而後將返回值inner子函數名賦值變量v1。若是bar函數內的資源沒有人佔用那麼就會銷燬,而這裏因爲函數的資源還有變量v1在使用因此沒有銷燬。[2]再次執行函數bar,並傳入參數syn,分析與第一步相同。[3]兩次調用同一個函數,可是兩次開闢的內存空間都是獨立的,傳入的參數也是不一樣的,而且在各自的內存空間中。當執行v1的時候,就是執行inner子函數,變量仍是找v1所在的函數空間,即打印yh。當執行v2的時候,就是執行inner子函數,變量仍是找v2所在的函數空間,即打印syn。
5)解釋閉包現象
def bar(name):
    def inner():
        print(name)
    return inner()  #沒有閉包,函數已經執行完畢
v1 = bar('yh')
#
空間不釋放,還被引用,空間還存在東西,沒有傳參也是閉包,函數執行終止了,內存尚未釋放,。
怎樣不是閉包,返回子函數返回值,子函數已經執行完畢沒人使用它的資源

9.4函數閉包問題

函數名指向函數代碼,每次執行此函數,新開闢一份空間,(將代碼複製過來)。因此屢次執行此函數
互不影響,它們有各自的空間。若是返回的值正在被調用,函數的這個空間不銷燬,調用以後才銷燬
看函數是由誰建立的,誰那裏有函數的入口

name = 'mcw'
def bar(name):
    def inner():
        print(name)
    return inner
v1 = bar('yh') # { name=yh, inner }  # 閉包,爲函數建立一塊區域(內部變量供本身使用),爲他

之後執行提供數據。
v2 = bar('syn') # { name=syn, inner }
v1()
v2()
----------------結果:
yh
syn
#函數執行分析:[1]執行bar函數並傳入參數yh後,系統會建立一個獨立的內存空間給函數bar,而後將返回值inner子函數名賦值變量v1。若是bar函數內的資源沒有人佔用那麼就會銷燬,而這裏因爲函數的資源還有變量v1在使用因此沒有銷燬。[2]再次執行函數bar,並傳入參數syn,分析與第一步相同。[3]兩次調用同一個函數,可是兩次開闢的內存空間都是獨立的,傳入的參數也是不一樣的,而且在各自的內存空間中。當執行v1的時候,就是執行inner子函數,變量仍是找v1所在的函數空間,即打印yh。當執行v2的時候,就是執行inner子函數,變量仍是找v2所在的函數空間,即打印syn。

 

十、Python內置函數的瞭解

Python 解釋器內置了不少函數和類型,您能夠在任什麼時候候使用它們。如下按字母表順序列出它們。

    內置函數    
abs() delattr() hash() memoryview() set()
all() dict() help() min() setattr()
any() dir() hex() next() slice()
ascii() divmod() id() object() sorted()
bin() enumerate() input() oct() staticmethod()
bool() eval() int() open() str()
breakpoint() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()  

 

  •  自定義函數

  • 內置函數

    • 其餘

    • len open  range  id  type  
    • 輸入輸出

    • print  input
    • 強制轉換

    • dict() list()  tuple()   int()  str()  bool()  set()  
    •  數學相關

      • abs,絕對值

        print(abs(1),abs(-1),abs(0))
        -------結果:
        1 1 0
      • float,轉換成浮點型(小數)

        print(float(3),float(0),float(2.5))
        ----------結果:
        3.0 0.0 2.5
      • max,找到最大值

        mcw=[2,1,4,3]
        print(max(mcw),min(mcw),sum(mcw))
        -----------結果:
        4 1 10
      • min,找最小值

        mcw=[2,1,4,3]
        print(max(mcw),min(mcw),sum(mcw))
        -----------結果:
        4 1 10
      • sum,求和

        mcw=[2,1,4,3]
        print(max(mcw),min(mcw),sum(mcw))
        -----------結果:
        4 1 10
        • divmod,兩數相除的商和餘數

          a,b = divmod(1001,5) print(a,b)
          # 練習題 請經過分頁對數據進行展現 """ 要求:  每頁顯示10條數據  讓用戶輸入要查看的頁面:頁碼 """
          USER_LIST = []  #此處生成列表元素[{'name': '魔降風雲變-1', 'email': '12337@qq.com'},{'name': '魔降風雲變-2', 'email': '12337@qq.com'}。。。。。]
          for i in range(1,836):
          temp = {'name':'魔降風雲變-%s' %i,'email':'123%s@qq.com' %i }
          USER_LIST.append(temp)
          def paging(num,data_list):
          """
          實現分頁功能
          :param num: 傳入分頁後每頁顯示的內容
          :param data_list: 傳入列表,將每一個列表元素分頁展現出來
          """
          total_count = len(data_list) # 數據總條數
          per_page_count= num # 每頁顯示10條
          max_page_num,a = divmod(total_count,per_page_count) # 總頁碼數
          if a>0:
          max_page_num += 1
          while True:
          try:
          page = int(input('要查看第幾頁:'))
          except Exception as e:
          print("輸入有誤!")
          if page < 1 or page> max_page_num:
          print('頁碼不合法,必須是 1 ~ %s' %max_page_num )
          else:
          start = (page-1) * per_page_count
          end = page * per_page_count
          data = data_list[start:end]
          for item in data:
          print(item)
          paging(4,USER_LIST)
          ------------------------------結果:

          要查看第幾頁:4
          {'name': '魔降風雲變-13', 'email': '12313@qq.com'}
          {'name': '魔降風雲變-14', 'email': '12314@qq.com'}
          {'name': '魔降風雲變-15', 'email': '12315@qq.com'}
          {'name': '魔降風雲變-16', 'email': '12316@qq.com'}
          要查看第幾頁:10000
          頁碼不合法,必須是 1 ~ 209
          要查看第幾頁:
          輸入有誤!
          頁碼不合法,必須是 1 ~ 209
          要查看第幾頁:10
          {'name': '魔降風雲變-37', 'email': '12337@qq.com'}
          {'name': '魔降風雲變-38', 'email': '12338@qq.com'}
          {'name': '魔降風雲變-39', 'email': '12339@qq.com'}
          {'name': '魔降風雲變-40', 'email': '12340@qq.com'}

           

          #總結:

    • 進制轉換相關

      • bin,將十進制轉化成二進制

        print(bin(4),bin(256))     #將十進制轉換爲二進制
        ----------結果:
        0b100 0b100000000
      • oct,將十進制轉換成八進制

        print(oct(3),oct(8),oct(18))    #十進制轉換爲8進制
        ------------結果:
        0o3 0o10 0o22
      • int,將其餘進制轉化成十進制

        a="0b1001"
        b="0o5"
        c="0xA"
        print(int(a,base=2),int(b,base=8),int(c,base=16))
        --------------結果:
        9 5 10
        
        
        a=0b1001
        b=0o5
        c=0xA
        print(int(a,base=2),int(b,base=8),int(c,base=16))
        -----------------結果:
            print(int(a,base=2),int(b,base=8),int(c,base=16))
        TypeError: int() can't convert non-string with explicit base
        
        a=0b1001
        print(type(a))
        b=0o5
        c=0xA
        print(int(a),int(b),int(c),type(a))
        ----------------結果:
        <class 'int'>
        9 5 10 <class 'int'>
        綜上:
        相似數字類型轉換爲十進制:int(0o**),int(0x**),int(0b**) #不用加base參數
        字符串類型轉換爲十進制s             #要加base參數
      • hex,將十進制轉換成十六進制

        print(hex(9),hex(10),hex(16),hex(20))  #將十進制轉換爲16進制
        -----------------------結果:
        0x9 0xa 0x10 0x14
      • 一道進制轉換的題

        # 1字節等於8位 # IP: 192.168.12.79 -> 001010010 . 001010010 . 001010010 . 001010010  # 1. 請將 ip = "192.168.12.79" 中的每一個十進制數轉換成二進制並經過,鏈接起來生成一個新的字符串。 
        ip="192.68.12.79"
        li=ip.split(".")
        li2=[]
        for i in li:
            # li2.append(str(bin(int(i))))
            li2.append(bin(int(i)))
        print(",".join(li2))
        -----------------結果:
        0b11000000,0b1000100,0b1100,0b1001111
        # 2.請將ip=192.168.12.79中的四個十進制數轉換成二進制,將四個二進制數拼接成一個二進制數並轉換爲 十進制。(注意:12轉換爲二進制位數不滿8位)
        # 0010100100001010010001010010001010010 -> 十進制的值。
        ip="192.168.12.79"
        li=ip.split(".")
        li2=[]
        for i in li:
            m=str(bin(int(i))).lstrip("0b")
            m="0"*(8-len(m))+m
            li2.append(m)
        mcw="".join(li2)
        print(int(mcw,base=2))
        ----------------結果:
        3232238671

bow使用:

1)函數有兩個必需參數x,y和一個可選參數z,結果返回x的y次冪乘(至關於x**y),若是可選參數z有傳入值,則返回冪乘以後再對z取模(至關於pow(x,y)%z)。
v1=pow(2,3)
v2=2**3
v3=pow(2,3,5)
v4=pow(2,3)%5
print([v1,v2,v3,v4])
----------------結果:
[8, 8, 3, 3]
二、全部的參數必須是數值類型
print(pow("3","2"))
----------結果:
print(pow("3","2"))
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'str'
三、若是x,y有一個是浮點數,則結果將轉換成浮點數。
print(pow(3.0,2))
--------------結果:
9.0
四、若是x,y都是整數,則結果也是整數,除非y是負數;若是y是負數,則結果返回的是浮點數,浮點數不能取模,全部可選參數z不能傳入值。
>>> pow(10,2)
100
>>> pow(2,4)
16
>>> pow(2,-4)
0.0625
>>> pow(2,-4,3)
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
pow(2,-4,3)
ValueError: pow() 2nd argument cannot be negative when 3rd argument specified
 5. 若是可選參數z傳入了值,x,y必須爲整數,且y不能爲負數。
>>> pow(2,3,5)
3
>>> pow(10,0.1,3)
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
pow(10,0.1,3)
TypeError: pow() 3rd argument not allowed unless all arguments are integers
>>> pow(10,-2,3)
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
pow(10,-2,3)
ValueError: pow() 2nd argument cannot be negative when 3rd argument specified
>>>

-- 編碼解碼相關:

1)chr,將十進制數字轉換成 unicode 編碼中的對應字符串。

print(chr(9798),chr(10087),chr(9787))
------------------結果:
♆ ❧ ☻

print(chr(9679),chr(9711),chr(9734),chr(9733))
-----------結果:
● ◯ ☆ ★
print([chr(i) for i in range(65,91)]) print([chr(i) for i in range(97,123)]) print(chr(65),chr(65+32),chr(90),chr(90+32)) -------------------結果: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] A a Z z

2)ord,根據字符在unicode編碼中找到其對應的十進制。

print(ord("A"),ord("a"),ord(""))
---------------結果:
65 97 9787

一些可能會用到的特殊符號(Unicode)

 3)map,循環每一個元素(第二個參數),而後讓每一個元素執行函數(第一個參數),將每一個函數執行的結果保存到新的列表中,並返回。

v1 = [11,22,33,44]
result = map(lambda x:x+100,v1)
print(list(result)) # 特殊
-------------結果:
[111, 122, 133, 144]

4)

v1 = [11,22,33,'asd',44,'xf']
def func(x):
    if type(x) == int:
        return True
    return False
result = filter(func,v1) # [11,]
print(list(result))
-------------結果:
[11, 22, 33, 44]

v1 = [11,22,33,'asd',44,'xf']
result = filter(lambda x: True if type(x) == int else False ,v1)
print(list(result))
result = filter(lambda x: type(x) == int ,v1)
print(list(result))
---------------結果:
[11, 22, 33, 44]
[11, 22, 33, 44]

5)reduce

import functools
v1 = ['','','','']
def func(x,y):
    return x+y
result = functools.reduce(func,v1)
print(result)
result = functools.reduce(lambda x,y:x+y,v1)
print(result)
----------------結果:
小馬過河
小馬過河

from functools import reduce
result = reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
print(result)
---------------結果:
15
原理圖:在這個例子裏,其實計算過程是這樣的:((((1+2)+3)+4)+5) ,累加的過程。還能夠實現階乘
來自:https://blog.csdn.net/caimouse/article/details/78129956

 6)dir()

dir() 函數不帶參數時,返回當前範圍內的變量、方法和定義的類型列表;帶參數時,返回參數的屬性、方法列表。若是參數包含方法__dir__(),該方法將被調用。若是參數不包含__dir__(),該方法將最大限度地收集參數信息。

import sys,os
print(dir(os))
----------------結果:
['DirEntry', 'F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'PathLike', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_fspath', '_get_exports_list', '_putenv', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'cpu_count', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'errno', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fsync', 'ftruncate', 'get_exec_path', 'get_handle_inheritable', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getenv', 'getlogin', 'getpid', 'getppid', 'isatty', 'kill', 'linesep', 'link', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'readlink', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sep', 'set_handle_inheritable', 'set_inheritable', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'st', 'startfile', 'stat', 'stat_float_times', 'stat_result', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sys', 'system', 'terminal_size', 'times', 'times_result', 'truncate', 'umask', 'uname_result', 'unlink', 'urandom', 'utime', 'waitpid', 'walk', 'write']

 

 

參考:https://docs.python.org/zh-cn/3/library/functions.html

十一、上述總結

沒傳參的函數,有傳參的函數,沒返回值的函數,有返回值的函數。既有傳參又有返回值的函數。須要
什麼樣的根據具體需求。
#自我總結

 

打印菱形

for i in range(1,4):
    a=" "*(5-i) +"*"*i +"*"*(i-1)
    print(a)
for i in range(2,4):
    b=" "*(i+1)+"*"*(3-i)+"*"*(4-i)
    print(b)

 


參考連接:
http://www.runoob.com/python3/python3-function.html
https://www.cnblogs.com/i-honey/p/7679897.html
http://c.biancheng.net/view/2248.html

參考續集

http://c.biancheng.net/view/2247.html

相關文章
相關標籤/搜索