Python——函數

来源:http://www.cnblogs.com/xinbing/archive/2017/09/07/7490865.html
-Advertisement-
Play Games

Python函數的定義的方法: ...


我們前面學的都是面向過程式的編程(代碼從上到下寫,並運行),而函數式編程是將繁雜的代碼通過整理特性進行規整。像圖書館一樣,將小說、教學、外文等書籍進行分類。讓編程人員或看代碼人員很容易的查看該段代碼的特性。並且可以重覆的利用該段代碼進行相同的操作、像圖書館書是公用的一樣,誰都可以去看,這樣又能便於觀察又能重覆使用,是日後主要使用的技術。

def test():         #設置一個函數名稱
    #test            #註釋函數作用
    print('函數式編程')  #函數程式處理邏輯
    return 0         #定義返回值,如果沒有定義將返回None
test()   #調用

函數:

1. 可以在調用時,在括弧內放入參數,裡面有(位置參數,關鍵字參數,混合參數,預設參數,彙總參數)

2. 位置參數必須要在關鍵字參數前面。

位置參數:

將參數一一對應,並傳入到函數中:

def func(a,b,c):
    print(a,c,b)
func(1,2,3)  #將1=>a,2=>b,3=>c

關鍵字參數:

將特定的參數以賦值形式對應起來。

def func(a,b,c):
    print(a,c,b)
func(a=1,b=2,c=8)

混合參數(位置參數與關鍵字參數)

不能寫在位置參數的前面:

def func(a,b,c):
    print(a,c,b)
test(3,b=2,c=1) √
test(c=1,2) X

預設參數:
調用函數的時候,預設參數非必須傳遞。
如果再沒有定義其他,就以預設的來。

在定義預設值時:不可變類型隨便傳,但可變類型需要註意:

def test(x,y=1):
print(y)

test(2)

彙總參數:

1. *args:接收N個位置參數,轉換成元組的形式。

def test1(x,*args):
  print(x)
  print(args)
test1(1,2,3,4,5,6) & test1(1,*[2,3,4,5,6]) #這裡的*後面的列表是將列表內容提取並重新賦值給元組,以元組形式輸出。

2. **kwargs:把N個關鍵字參數,轉換成字典的方式。

def test1(x,**kwargs):
    print(x)
    print(kwargs)
# test1(1,name='3',age=20)
test1(2,name='xuan',age=9)
test1(1,**{'name':"xuan",'age':20})   #將字典內容提取,在重新賦值給函數內的kwargs
2
{'name': 'xuan', 'age': 9}
1
{'name': 'xuan', 'age': 20}

作用域:

在Python中,一個函數就是一個作用域,而所有的函數都掛靠在.py文件的總作用域中。

在這裡寫的代碼分為:全局作用域和局部作用域

1. 全局作用域

  • 要使用全大寫形式定義變數名稱,為了將局部變數做標識。
  • 局部作用域全部掛靠在全局作用域內
NAME = 'a1'
def func():
    name = 'a2'   
    print(name)
print(NAME)
func()

2. 局部作用域:

  • 局部作用域可以調用全局作用域。局部和局部,全局和局部不能調用。
  • 局部作用域之間無法調用,可以使用父作用域。
def change_name(name): #一個函數叫做一個作用域,
  print('before change',name)
  name='XB' 
  print('after change',name)

name = 'xb'
change_name(name)
print(name)

global:

在局部作用域中,進行全局作用域內容的查找,並可以修改。(只能修改可變類型,不可變類型為局部內重新賦值)

NAME = 'a1'
def func():
    global NAME
    NAME = 'bbb'
func()
print(NAME)

nonlocal:

在子局部作用域中,進行對父級局部作用域的內容查找不更改全局作用域內容,並可以修改。(同樣修改可變類型,不可變類型為局部內重新賦值)

NAME = 'a1'
def func():
    NAME = '111'
    def func2():
        nonlocal NAME
        NAME = 'bbb'
    func2()
    print(NAME)
func()
print(NAME)

返回值:

在函數中使用return來進行函數這個子作用域的返回值的關鍵字。其中:

1. 預設如果沒有return,但定義了取值變數的話,預設為None。

def papa():
    print('111')
a = papa()   #a就是None

2. 如果只有一個返回值,那麼就返回相應的數值和數據類型。如果有多個返回值,那麼將返回一個元組。

def papa():
    dic = {'k1':'v1'}
    return dic   #將返回字典類型
    return {'k1':'v1'},{'k1':'v1'},{'k1':'v1'}  #將返回元組類型

a = papa()   
print(a)

3. 返回值同樣可以返回另一個函數的記憶體對象地址

def a():
    print('111')
def papa():
    return a  #返回一個記憶體對象地址,返回後可以直接運行。
b = papa()
b()lam

lambda

用於表示簡單的函數時,可以使用lambda來進行,其中需要註意的:

1. 只能用一行來表示lambda

2. 只能用參數傳的值,而不能自己定義一個變數。

使用lambda預設就會有一個return。

a = lambda : 1+1   #將1+1的結果返回到a中。
print(a())

lambda可以搭配三元運算使用:

a = lambda : 1 if 1+1 == 2  else 2   #判斷如果1+1等於2的話,那麼返回1,否則返回2
print(a())

其他:

lis = lambda : [ i for i in range(10) if i%3 == 0 ]   #迴圈1-10,判斷其中哪些為3整除,添加到列表中,生成一個lambda。
print(lis())

閉包:

閉包是嵌套在函數中的函數,而閉包必須是內層函數對外層函數的變數(非全局變數)的引用。

為函數創建一個區域(內部變數供自己使用)為以後執行提供數據。

#實例
li = []
def func(new_value):
    li.append(new_value)
    total = sum(li)
    return  total/len(li)
print(func(1000))
print(func(2000))
print(func(5000))

#那麼問題來了,li是全局變數,我可以在全局隨意更改。
li = []
def func(new_value):
    li.append(new_value)
    total = sum(li)
    return  total/len(li)
print(func(1000))
print(func(2000))
li.append(120301)
print(func(5000))
#得出來的結果就大不相同了。如何有解決辦法,那就是把li放到函數的小作用域里。

def func(new_value):
    li = []
    li.append(new_value)
    total = sum(li)
    return  total/len(li)
print(func(1000))
print(func(2000))
print(func(5000))
#這樣一來,每次運行函數,就會新生成一個新的列表出來。那麼值就沒有變化了。接下來如何解決這個問題。閉包就來了。

def func():
    li = []
    def func1(new_value):
        li.append(new_value)
        total = sum(li)
        return  total/len(li)
    return func1
func = func()
print(func(1000))
print(func(2000))
print(func(5000))

#這樣一來,即不會出現全局模式更改的問題,也不會擔心列表重新生成的問題。這就是比好。

其中,下麵一塊區域叫做閉包:

    li = []
    def func1(new_value):
        li.append(new_value)
        total = sum(li)
        return  total/len(li)

我們可以通過查看函數內是否有自由變數來側面證明是不是閉包。

def func():
    li = []
    def func1(new_value):
        li.append(new_value)
        total = sum(li)
        return  total/len(li)
    return func1
func = func()
print(func.__code__.co_freevars)  #查看函數的自由變數
#('li',)
print(func.__code__.co_varnames)   #查看函數的局部變數
#('new_value', 'total')

函數需要註意的點:

1. 根據數據類型的不同,有些是有返回值的,有些是沒有返回值的。

lis = []
def a():
    return  lis.append('111')
b = a()
print(b)   #由於列表形式的添加是沒有返回值的,所以返回的是None
lis = '123'
def a():
    return  lis + '321'
b = a()
print(b)   #由於字元串是有返回值的,所以返回的是所需值

2. 需要判斷是傳入函數記憶體地址還是函數的return的值。

def func():
    print('1111')
    return 0
lis = [func,func,func]  #這裡傳入的是函數的記憶體地址。不是執行結果。
for item in lis:
    print(item)      #列印的是記憶體地址
'''
<function func at 0x000001D8489B9550>
<function func at 0x000001D8489B9550>
<function func at 0x000001D8489B9550>
'''
def func():
    return 0
lis = [func(),func(),func()]  #這裡傳入的是運行完func的返回值
for item in lis:
    print(item)      #列印的是0
'''
0
0
0
'''

3. 閉包問題

def func(name):
    v = lambda x:x+name
    return v

v1 = func('武沛齊')
v2 = func('alex')
v3 = v1('銀角')
v4 = v2('金角')
print(v1,v2,v3,v4)

result = []
for i in range(10):
    func = lambda : i      # 註意:函數不執行,內部代碼不會執行。
    result.append(func)

print(i)
print(result)
v1 = result[0]()
v2 = result[9]()
print(v1,v2)

def func(num):
    def inner():
        print(num)
    return inner

result = []
for i in range(10):
    f = func(i)
    result.append(f)

print(i)   
print(result)  
v1 = result[0]()   
v2 = result[9]()   
print(v1,v2)  

4. 實參與形參

傳參的類型是否為可變類型,如果可變類型,那麼實參也會一起改變,如果是不可變類型,那麼就會重新創建一個方法內部變數。

###########傳入不可變類型############
def func(a):
    a += 1
    print(id(a))
a = 7
func(a)
print(id(a))
print(a)

#判斷ID輸出是否一樣,a輸出的結果?
############傳入可變類型###################

def func(a):
    a[0] = 8
    print(id(a))
a = [1,2,3]
func(a)
print(id(a))
print(a)
#判斷ID輸出是否一樣,a輸出的結果?

函數中的那些坑:

1. 函數中有定義一個空列表作為形參:

def a(b,lis=[])

問題:在沒有傳入新的列表當做實參時,將會使用定義好的空列表,那麼將會導致多個沒有定義的實參重覆調用該空列表。這將導致數據內容不一致的問題。

def b(a,lis=[]):
    for i in range(a):
        lis.append(i*i)
    print(lis)
b(3)
b(3)
b(3)
'''
[0, 1, 4]
[0, 1, 4, 0, 1, 4]
[0, 1, 4, 0, 1, 4, 0, 1, 4]
'''

可以傳參時傳入一個自己的空列表,那麼就將使用自己傳入的空列表。

def b(a,lis=[]):
    for i in range(a):
        lis.append(i*i)
    print(lis)
b(3,[])
b(3,[])
b(3,[])
'''
[0, 1, 4]
[0, 1, 4]
[0, 1, 4]
'''

如何解決這類問題,要麼就刪除空列表,要麼就進行判斷。

def b(a,lis=[]):
    if lis:
        lis = []
    for i in range(a):
        lis.append(i*i)
    print(lis)
b(3,[])
b(3,[])
b(3)
b(3)
b(3)
'''
[0, 1, 4]
[0, 1, 4]
[0, 1, 4]
'''

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 走過的彎路: 1. DoWork方法中不能操縱UI控制項。 2. DoWork事件中調用ReportProgress方法,在ProgressChanged事件中可以操縱UI控制項。 3. WorkerReportsProgress屬性必須設置true. (預設是false. 因為這塊,費了不少時間找原因 ...
  • 【才疏學淺,難免有紕漏,若有不正確的地方,歡迎指教】 MFC中有一個庫函數 Tokenize(); 函數原型:CStringT Tokenize( PCXSTR pszTokens , int& iStart ) const; 這個函數可以根據某個字元將CString分隔開。 事先設定好緩衝區,被分 ...
  • SOAP 簡單對象訪問協議, webService三要素 , SOAP、WSDL(WebServicesDescriptionLanguage)、UDDI(UniversalDescriptionDiscovery andIntegration)之一, soap用來描述傳遞信息的格式, WSDL 用 ...
  • 錯誤原因:Mapper對應的XXXMapper.xml中的\標簽的resultType和resultMap搞混了,resultType需要對應一個類,而resultMap對應\標簽中定義的映射。關於兩者的區別可見:http://blog.csdn.net/woshixuye/article/deta ...
  • 本文藉鑒了同事 JayChang的研究成果,這裡是他的博客:http://jaychang.cn/ http://jaychang.iteye.com/category/105859 ...
  • 函數:startswith() 作用:判斷字元串是否以指定字元或子字元串開頭一、函數說明語法:string.startswith(str, beg=0,end=len(string)) 或string[beg:end].startswith(str) 參數說明:string: 被檢測的字元串str: ...
  • 1、pom xml 配置 2、 項目結構 兩個文件的內容 3、編譯項目,編譯後的目錄結構 classes 類路徑下context.text 的內容 ...
  • Python在數據科學盛行的今天,其易於閱讀和編寫的特點,越來越受編程者追捧。在IEEE發佈的2017年編程語言排行榜中,Python也高居首位。如果你有學Python的計劃,快來看看小編分享的Python教程。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...