日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

新手上路必学的Python函数基础知识,全在这里了(多段代码举例)

發布時間:2025/3/15 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 新手上路必学的Python函数基础知识,全在这里了(多段代码举例) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導讀:函數是Python中最重要、最基礎的代碼組織和代碼復用方式。根據經驗,如果你需要多次重復相同或類似的代碼,就非常值得寫一個可復用的函數。通過給一組Python語句一個函數名,形成的函數可以幫助你的代碼更加可讀。


函數聲明時使用def關鍵字,返回時使用return關鍵字:


def?my_function(x,?y,?z=1.5):??

if?z?>?1:??

????return?z?*?(x?+?y)??

else:??

????return?z?/?(x?+?y)??


有多條返回語句是沒有問題的。如果Python達到函數的尾部時仍然沒有遇到return語句,就會自動返回None。


每個函數都可以有位置參數和關鍵字參數。關鍵字參數最常用于指定默認值或可選參數。在前面的函數中,x和y是位置參數,z是關鍵字參數。這意味著函數可以通過以下任意一種方式進行調用:


my_function(5,?6,?z=0.7)??

my_function(3.14,?7,?3.5)??

my_function(10,?20)??


函數參數的主要限制是關鍵字參數必須跟在位置參數后(如果有的話)。你可以按照任意順序指定關鍵字參數;這可以讓你不必強行記住函數參數的順序,而只需用參數名指定。


也可以使用關鍵字參數向位置參數傳參。在前面的例子中,我們也可以這樣寫:


my_function(x=5,?y=6,?z=7)??

my_function(y=6,?x=5,?z=7)??


在部分場景中,這樣做有助于代碼可讀性



01 命名空間、作用域和本地函數


函數有兩種連接變量的方式:全局、本地。在Python中另一種更貼切地描述變量作用域的名稱是命名空間。在函數內部,任意變量都是默認分配到本地命名空間的。本地命名空間是在函數被調用時生成的,并立即由函數的參數填充。當函數執行結束后,本地命名空間就會被銷毀(除了一些特殊情況)。考慮以下函數:


def?func():??

????a?=?[]??

????for?i?in?range(5):??

????????a.append(i)??


當func()調用時,空的列表會被創建,五個元素被添加到列表,之后a會在函數退出時被銷毀。假設我們像下面這樣聲明a:


a?=?[]??

def?func():??

????for?i?in?range(5):??

????????a.append(i)??


在函數外部給變量賦值是可以的,但是那變量必須使用global關鍵字聲明為全局變量:


In?[168]:?a?=?None??

In?[169]:?def?bind_a_variable():??

.....:????????global?a??

.....:????????a?=?[]??

.....:????????bind_a_variable()??

.....:??

In?[170]:?print(a)??

[]??


我簡單的講下global關鍵字的用法。通常全局變量用來存儲系統中的某些狀態。如果你發現你大量使用了全局變量,可能表明你需要面向對象編程(使用類)



02 返回多個值


當我在使用Java和C++編程后第一次使用Python編程時,我最喜歡的特性就是使用簡單語法就可以從函數中返回多個值。以下是代碼:


def?f():??

a?=?5??

b?=?6??

c?=?7??

return?a,?b,?c??

a,?b,?c?=?f()??


在數據分析和其他科研應用,你可能會發現經常需要返回多個值。這里實質上是返回了一個對象,也就是元組,而元組之后又被拆包為多個結果變量。在前面的例子中,我們可以用下面的代碼代替:


return_value?=?f()??


在這個例子中,return_value是一個3個元素的元組。像之前那樣一次返回多個值還有一種潛在的、更有吸引力的實現:


def?f():??

a?=?5??

b?=?6??

c?=?7??

return?{'a'?:?a,?'b'?:?b,?'c'?:?c}??


具體用哪種技術取決于你需要做什么的事。



03 函數是對象


由于Python的函數是對象,很多在其他語言中比較難的構造在Python中非常容易實現。假設我們正在做數據清洗,需要將一些變形應用到下列字符串列表中:


In?[171]:?states?=?['?Alabama?',?'Georgia!',?'Georgia',?'georgia',?'FlOrIda',??

.....:?'south?carolina##',?'West?virginia?']??


任何處理過用戶提交數據的人都對這樣的數據感到凌亂。為了使這些數據整齊、可用于分析,有很多是事情需要去做:去除空格、移除標點符號、調整適當的大小寫。一種方式是使用內建的字符串方法,結合標準庫中的正則表達式模塊re:


import?re??

def?clean_strings(strings):??

????result?=?[]??

????for?value?in?strings:??

????????value?=?value.strip()??

????????value?=?re.sub('[!#?]',?'',?value)??

????????value?=?value.title()??

????????result.append(value)??

????return?result??


結果如下:


In?[173]:?clean_strings(states)??

Out[173]:??

['Alabama',??

'Georgia',??

'Georgia',??

'Georgia',??

'Florida',??

'South?Carolina',??

'West?Virginia']??


另一種會讓你覺得有用的實現就是將特定的列表操作應用到某個字符串的集合上:


def?remove_punctuation(value):??

return?re.sub('[!#?]',?'',?value)??

clean_ops?=?[str.strip,?remove_punctuation,?str.title]??

def?clean_strings(strings,?ops):??

????result?=?[]??

????for?value?in?strings:??

????????for?function?in?ops:??

????????????value?=?function(value)??

????????result.append(value)??

????return?result?


結果如下:


In?[175]:?clean_strings(states,?clean_ops)??

Out[175]:??

['Alabama',??

'Georgia',??

'Georgia',??

'Georgia',??

'Florida',??

'South?Carolina',??

'West?Virginia']??


像這種更為函數化的模式可以使你在更高層次上方便地修改字符串變換方法。clean_strings函數現在也具有更強的復用性、通用性。


你可以將函數作為一個參數傳給其他的函數,比如內建的map函數,可以將一個函數應用到一個序列上:


In?[176]:?for?x?in?map(remove_punctuation,?states):??

.....:????????print(x)??

Alabama??

Georgia??

Georgia??

georgia??

FlOrIda??

south?carolina??

West?virginia??



04 匿名(Lambda)函數


Python支持所謂的匿名或lambda函數。匿名函數是一種通過單個語句生成函數的方式,其結果是返回值。匿名函數使用lambda關鍵字定義,該關鍵字僅表達“我們聲明一個匿名函數”的意思:


def?short_function(x):??

????return?x?*?2??

equiv_anon?=?lambda?x:?x?*?2??


匿名函數在數據分析中非常方便,因為在很多案例中數據變形函數都可以作為函數的參數。匿名函數代碼量小(也更為清晰),將它作為參數進行傳值,比寫一個完整的函數或者將匿名函數賦值給局部變量更好。舉個例子,考慮下面的不佳示例:


def?apply_to_list(some_list,?f):??

????return?[f(x)?for?x?in?some_list]??

ints?=?[4,?0,?1,?5,?6]??

apply_to_list(ints,?lambda?x:?x?*?2)??


你也可以寫成[x * 2 for x in ints] ,但是在這里我們能夠簡單地將一個自定義操作符傳遞給apply_to_list函數。


另一個例子,假設你想要根據字符串中不同字母的數量對一個字符串集合進行排序:


In?[177]:?strings?=?['foo',?'card',?'bar',?'aaaa',?'abab']??


這里我們可以將一個匿名函數傳給列表的sort方法:


In?[178]:?strings.sort(key=lambda?x:?len(set(list(x))))??

In?[179]:?strings??

Out[179]:?['aaaa',?'foo',?'abab',?'bar',?'card']??


和def關鍵字聲明的函數不同,匿名函數對象自身并沒有一個顯式的__name__ 屬性,這是lambda函數被稱為匿名函數的一個原因。



05 柯里化:部分函數應用


柯里化是計算機科學術語(以數學家Haskell Curry命名),它表示通過部分參數應用的方式從已有的函數中衍生出新的函數。例如,假設我們有一個不重要的函數,其功能是將兩個數加一起:


def?add_numbers(x,?y):??

return?x?+?y??


使用這個函數,我們可以衍生出一個只有一個變量的新函數,add_five,可以給參數加上5:


add_five?=?lambda?y:?add_numbers(5,?y)??


第二個參數對于函數add_numers就是柯里化了。這里并沒有什么神奇的地方,我們真正做的事只是定義了一個新函數,這個新函數調用了已經存在的函數。內建的functools模塊可以使用pratial函數簡化這種處理:


from?functools?import?partial??

add_five?=?partial(add_numbers,?5)??



06 生成器


通過一致的方式遍歷序列,例如列表中的對象或者文件中的一行行內容,這是Python的一個重要特性。這個特性是通過迭代器協議來實現的,迭代器協議是一種令對象可遍歷的通用方式。例如,遍歷一個字典,獲得字典的鍵:


In?[180]:?some_dict?=?{'a':?1,?'b':?2,?'c':?3}??

In?[181]:?for?key?in?some_dict:??

.....:????????print(key)??

a???

b??

c??


當你寫下for key in some_dict 的語句時,Python解釋器首先嘗試根據some_dict生成一個迭代器:


In?[182]:?dict_iterator?=?iter(some_dict)??

In?[183]:?dict_iterator??

Out[183]:?<dict_keyiterator?at?0x7fbbd5a9f908>??


迭代器就是一種用于在上下文中(比如for循環)向Python解釋器生成對象的對象。大部分以列表或列表型對象為參數的方法都可以接收任意的迭代器對象。包括內建方法比如min、max和sum,以及類型構造函數比如list和tuple:


In?[184]:?list(dict_iterator)??

Out[184]:?['a',?'b',?'c']??


用迭代器構造新的可遍歷對象是一種非常簡潔的方式。普通函數執行并一次返回單個結果,而生成器則“惰性”地返回一個多結果序列,在每一個元素產生之后暫停,直到下一個請求。如需創建一個生成器,只需要在函數中將返回關鍵字return替換為yield關鍵字:


def?squares(n=10):??

print('Generating?squares?from?1?to?{0}'.format(n?**?2))??

for?i?in?range(1,?n?+?1):??

????yield?i?**?2??


當你實際調用生成器時,代碼并不會立即執行:


In?[186]:?gen?=?squares()??

In?[187]:?gen??

Out[187]:?<generator?object?squares?at?0x7fbbd5ab4570>??


直到你請求生成器中的元素時,它才會執行它的代碼:


In?[188]:?for?x?in?gen:??

.....:?print(x,?end='?')??

Generating?squares?from?1?to?100??

1?4?9?16?25?36?49?64?81?100??


1. 生成器表達式


生成器表達式來創建生成器更為簡單。生成器表達式與列表、字典、集合的推導式很類似,創建一個生成器表達式,只需要將列表推導式的中括號替換為小括號即可:


In?[189]:?gen?=?(x?**?2?for?x?in?range(100))??

In?[190]:?gen??

Out[190]:?<generator?object?<genexpr>?at?0x7fbbd5ab29e8>??


上面的代碼與下面更為復雜的生成器是等價的:


def?_make_gen():??

for?x?in?range(100):??

????yield?x?**?2??

gen?=?_make_gen()??


在很多情況下,生成器表達式可以作為函數參數用于替代列表推導式:


In?[191]:?sum(x?**?2?for?x?in?range(100))??

Out[191]:?328350??

In?[192]:?dict((i,?i?**2)?for?i?in?range(5))??

Out[192]:?{0:?0,?1:?1,?2:?4,?3:?9,?4:?16}??


2. itertools模塊


標準庫中的itertools模塊是適用于大多數數據算法的生成器集合。例如,groupby可以根據任意的序列和一個函數,通過函數的返回值對序列中連續的元素進行分組,參見下面的例子:


In?[193]:?import?itertools??

In?[194]:?first_letter?=?lambda?x:?x[0]??

In?[195]:?names?=?['Alan',?'Adam',?'Wes',?'Will',?'Albert',?'Steven']??

In?[196]:?for?letter,?names?in?itertools.groupby(names,?first_letter):??

.....:????????print(letter,?list(names))?#?names是一個生成器??

A?['Alan',?'Adam']??

W?['Wes',?'Will']??

A?['Albert']??

S?['Steven']??


下表是一些我認為經常用到的itertools函數的列表。你可以通過查詢Python官方文檔來獲得更多關于內建工具庫的信息。


函數

描述

combinations(iterable, ?k)

根據iterable參數中的所有元素生成一個包含所有可能K元組的序列,忽略元素的順序,也不進行替代(需要替代請參考函數 combinations_with_replacement )

permutations(iterable, ?k)

根據itrable參數中的按順序生成包含所有可能K元組的序列

groupby(iterable[, ?keyfunc])

根據每一個獨一的Key生成 (key, sub-iterator) 元組

product(*iterables, ?repeat=1)

以元組的形式,根據輸入的可遍歷對象們生成笛卡爾積,與嵌套的for循環類似



07 錯誤和異常處理


優雅地處理Python的錯誤或異常是構建穩定程序的重要組成部分。在數據分析應用中,很多函數只能處理特定的輸入。例如,Python的float函數可以將字符串轉換為浮點數字,但是對不正確的輸入會產生ValueError:


In?[197]:?float('1.2345')??

Out[197]:?1.2345??

In?[198]:?float('something')??

---------------------------------------------------------------------------??

ValueError?Traceback?(most?recent?call?last)??

<ipython-input-198-439904410854>?in?<module>()??

---->?1?float('something')??

ValueError:?could?not?convert?string?to?float:?'something'??


假設我們想要在float函數運行失敗時可以優雅地返回輸入參數。我們可以通過將float函數寫入一個try/except代碼段來實現:


def?attempt_float(x):??

try:??

????return?float(x)??

except:??

????return?x??


如果float(x)執行時拋出了異常,則代碼段中的except部分代碼將會被執行:


In?[200]:?attempt_float('1.2345')??

Out[200]:?1.2345??

In?[201]:?attempt_float('something')??

Out[201]:?'something??


你可能會注意到,除了ValueError,float函數還會拋出其他的異常:


In?[202]:?float((1,?2))??

---------------------------------------------------------------------------??

TypeError?Traceback?(most?recent?call?last)??

<ipython-input-202-842079ebb635>?in?<module>()??

---->?1?float((1,?2))??

TypeError:?float()?argument?must?be?a?string?or?a?number,?not?'tuple'??


你可能只想處理ValueError,因為TypeError(輸入的不是字符串或數值)可能表明你的程序中有個合乎語法的錯誤。為了實現這個目的,在except后面寫下異常類型:


def?attempt_float(x):??

try:??

????return?float(x)??

except?ValueError:??

????return?x??


然后我們可以得到:


In?[204]:?attempt_float((1,?2))??

---------------------------------------------------------------------------??

TypeError?Traceback?(most?recent?call?last)??

<ipython-input-204-9bdfd730cead>?in?<module>()??

---->?1?attempt_float((1,?2))??

<ipython-input-203-3e06b8379b6b>?in?attempt_float(x)??

1?def?attempt_float(x):??

2?try:??

---->?3?return?float(x)??

4?except?ValueError:??

5?return?x??

TypeError:?float()?argument?must?be?a?string?or?a?number,?not?'tuple'??


你可以通過將多個異常類型寫成元組的方式同事捕獲多個異常(小括號是必不可少的):


def?attempt_float(x):??

try:??

????return?float(x)??

except?(TypeError,?ValueError):??

????return?x??


某些情況下,你可能想要處理一個異常,但是你希望一部分代碼無論try代碼塊是否報錯都要執行。為了實現這個目的,使用finally關鍵字:


f?=?open(path,?'w')??

try:??

????write_to_file(f)??

finally:??

????f.close()??


這樣,我們可以讓f在程序結束后總是關閉。類似的,你可以使用else來執行當try代碼塊成功執行時才會執行的代碼:


f?=?open(path,?'w')??

try:??

????write_to_file(f)??

except:??

????print('Failed')??

else:??

????print('Succeeded')??

finally:??

????f.close()??


IPython中的異常


如果當你正在%run一個腳本或執行任何語句報錯時,IPython將會默認打印出完整的調用堆棧跟蹤(報錯追溯),會將堆棧中每個錯誤點附近的幾行上下文代碼打印出:


In?[10]:?%run?examples/ipython_bug.py??

---------------------------------------------------------------------------??

AssertionError?Traceback?(most?recent?call?last)??

/home/wesm/code/pydata-book/examples/ipython_bug.py?in?<module>()??

13?throws_an_exception()??

14??

--->?15?calling_things()??

/home/wesm/code/pydata-book/examples/ipython_bug.py?in?calling_things()??

11?def?calling_things():??

12?works_fine()??

--->?13?throws_an_exception()??

14??

15?calling_things()??

/home/wesm/code/pydata-book/examples/ipython_bug.py?in?throws_an_exception()??

7?a?=?5??

8?b?=?6??

---->?9?assert(a?+?b?==?10)??

10??

11?def?calling_things():??

AssertionError:??


比標準Python解釋器提供更多額外的上下文是IPython的一大進步(標準Python解釋器不提供任何額外的上下文)。你可以使用%xmode命令來控制上下文的數量,可以從Plain(普通)模式(與標準Python解釋器一致)切換到Verbose(復雜)模式(可以顯示函數的參數值以及更多有用信息)。


關于作者:韋斯·麥金尼(Wes McKinney)是流行的Python開源數據分析庫pandas的創始人。他是一名活躍的演講者,也是Python數據社區和Apache軟件基金會的Python/C++開源開發者。目前他在紐約從事軟件架構師工作。


本文摘編自《利用Python進行數據分析》(原書第2版),經出版方授權發布。


延伸閱讀《利用Python進行數據分析

轉載請聯系微信:togo-maruko

點擊文末右下角“寫留言”發表你的觀點


推薦語:適合剛學Python的數據分析師或剛學數據科學以及科學計算的Python編程者。閱讀本書可以獲得一份關于在Python下操作、處理、清洗、規整數據集的完整說明。



更多精彩


在公眾號后臺對話框輸入以下關鍵詞

查看更多優質內容!


PPT?|?報告?|?讀書?|?書單?|?干貨

Python?|?機器學習?|?深度學習?|?神經網絡

區塊鏈?|?揭秘?|?高考?|?福利


猜你想看


  • pandas創始人手把手教你利用Python進行數據分析(思維導圖)

  • 百度吹過的牛實現了,你的呢?5本書帶你搞定AI前沿技術

  • 程序猿們,如果你不想跑偏,就千萬別讀這4本書!

  • 20位大佬組團“踢館”,誰超越了圖靈?



Q:?你都會用到哪些Python的函數

歡迎留言與大家分享

覺得不錯,請把這篇文章分享給你的朋友

轉載 / 投稿請聯系:baiyu@hzbook.com

更多精彩,請在后臺點擊“歷史文章”查看

點擊閱讀原文,了解更多

新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的新手上路必学的Python函数基础知识,全在这里了(多段代码举例)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。