亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

【跟著Head First學python】4、代碼重用:函數與模塊

系統 1603 0

1、函數

相比于C++,python中寫一個函數需要一個關鍵字def。其主要結構如下:

            
              def 函數名(函數參數):
"""函數文檔,docstring"""
    函數體
    return
            
          

如果一個函數是一個類的一部分,它就稱為一個方法。

注意函數沒有類型信息,無論是函數參數還是返回值,都不需要類型信息,當然為了便于閱讀,可以使用函數注解。

函數注解是py3新增的一項功能,類似注釋,它們只負責提高程序的可讀性,而不會對程序功能做出任何改變。

推薦python代碼為了可讀性,遵循PEP8的規范。以下是一個例程:

            
              def search4vowels(word):
    """Display any vowels found in an asked-for word."""
    vowels=set('aeiou')
    found=vowels.intersection(set(word))
    for vowel in found:
        print(vowel)
            
          

效果如下:

【跟著Head First學python】4、代碼重用:函數與模塊_第1張圖片

可以看得出來,犯了很多愚蠢的錯誤。首先,最重要的是,雖然沒有為函數的參數指定類型,但函數參數必須有類型,像我第一次那樣,參數直接是chy是肯定不行的,單獨的chy會被編譯器認為是一個變量而不是一個字符串;另外,第二次沒有輸入參數,會報缺少參數的錯誤,第三次直接把函數名打錯了,最后一次,加了單引號,得到正確結果。

在python中,每一個對象都有一個與之關聯的真值,表示這個對象為True或者False。如果該對象計算為0、值為None、是一個空串或一個空的數據結構,那么就是False,否則是True。使用函數bool來計算對象的真值。嚴格來說,所有的非空數據結構都計算為True。

默認來說,函數使用return關鍵字來返回值,只能返回一個值,若想返回多個值,就需要使用數據結構,這和C++中類似。

將上面的函數改為返回word中的元音,如下:

            
              def search4vowels(word):
    """Display any vowels found in an asked-for word."""
    vowels=set('aeiou')
    return vowels.intersection(set(word))

            
          

效果如下:

注意,當word中不含元音時,應該返回一個空集合。由于集合使用{}包圍,那么空集合應該返回{}。但是返回的是set()。這是因為,{}沒法區分是空集合還是空字典,因此用{}表示空字典,用set()表示空集合。

上述代碼加入注解后的效果如下:

            
              def search4vowels(word:str)->set:
    """Display any vowels found in an asked-for word."""
    vowels=set('aeiou')
    return vowels.intersection(set(word))
            
          

在運行時,加不加注解沒有任何區別,只有在使用help時有區別:

【跟著Head First學python】4、代碼重用:函數與模塊_第2張圖片

help會把注解顯示,還會把docstring也顯示。

接下來,定義一個更泛用的函數,用于找到兩個字符串中所有相同字符的集合,代碼如下:

            
              def search4vowels(phrase:str)->set:
    """Display any vowels found in a supplied phrase."""
    vowels=set('aeiou')
    return vowels.intersection(set(word))


def search4letters(phrase:str,letters:str)->set:
    """Return a aet of the 'letters' found in 'phrase'."""
    return set(letters).intersection(set(phrase))
            
          

可以在一個文件中定義多個函數,注意,根據PEP8,兩個函數間要空兩行。這里的第二個函數search4letters用于實現找到兩個字符串的交集。注意,第一個函數是第二個函數在letters=‘aeiou’情況下的特例,因此,如果能夠讓letters默認為aeiou,那么就可以實現函數二對函數一的完全代替。這樣就可以實現函數的可重用。

如何實現呢?很簡單,在參數注解的后面加入默認值即可,如下:

            
              def search4letters(phrase:str,letters:str='aeiou')->set:
    """Return a aet of the 'letters' found in 'phrase'."""
    return set(letters).intersection(set(phrase))
            
          

這樣,當我們在調用search4letters函數時,若只用了一個參數,那么就默認第二個參數是aeiou;若用了兩個參數,那么letters就不再是默認值。默認值與初值不同,不要搞混。默認值只有在def行才能修改。

與C++不同的是,python提供了兩種參數賦值方法,位置賦值與關鍵字賦值。其中,位置賦值的情況下,對函數的調用與C++中相同,即函數f(A,B,C)調用時就是f(1,2,3),其中A=1,B=2,C=3。然而,關鍵字賦值的情況下,參數順序就沒用了,調用f可以是f(C=3,A=1,B=2),即點名某個參數等于多少。這樣就不用記住參數順序了,當然缺點就是要多打一些字。

2、模塊

好,既然在1中,我們已經寫好了函數,那么,如何實現它的可重用呢?

如果調用函數的代碼就在函數文件里,那直接用就好了,但是如果多個文件都要用這個函數,那每個文件里都把這個函數重新寫一遍,那就太蠢了。要使用import。

我們已經知道了,import是用來引入模塊的,也就是說,已經有了函數,還要把它打包成一個模塊,才能在其他文件中調用這個函數。

首先來看import如何引入模塊。

使用import A引入一個名為A的模塊,編譯器會去三個地方找這個叫A的模塊:首先在當前工作目錄找,然后去解釋器的site-package找,最后去標準庫位置找。找到了的話,直接引入,沒找到就報錯。

當前工作目錄,這個概念我是在linux中了解到的。在win中,用cmd進入命令行

【跟著Head First學python】4、代碼重用:函數與模塊_第3張圖片

那么這里的C:\Users\Amarantine就是當前工作目錄,可以用cd來換工作目錄。

如果我們import的模塊不在工作目錄中,那就會報錯。

因此,要想使用一個模塊,可以把它放在我們的當前工作目錄里,但是這樣太麻煩了。更好的方法是放在site-package里,這里放著的都是第三方的python模塊。標準庫模塊不要想了,那不是我們能染指的。

在py3.4中,引入了一個新的模塊,setuptools,使用這個模塊可以較為方便的在site-package中加入我們自己的模塊,僅需三步:

①、創建一個發布描述

至少需要兩個描述文件,一個是setup.py安裝文件,一個是README.txt解釋文件。這兩個文件必須放在和函數源碼文件相同的文件夾中。setup文件中的代碼幾乎是定死的,以發布vsearch這個模塊為例,其代碼如下:

            
              from setuptools import setup
setup(
    name='vsearch',
    version='1.0',
    description='The Head First Python Search Tools',
    author='Osiris',
    author_email='123456@qq.com',
    url='baidu.com',
    py_modules=['vsearch'],
    )

            
          

重要的參數有兩個,一個是name,其值是發布的包的名字;另一個是py_modules,其值是文件夾中所有py文件的列表。注意,這里py_modules即使填寫錯誤,也不會報錯。我第一次就是把vsearch打成了vresearch導致安裝成功卻import失敗。很是蛋疼。

txt文件可以為空。

如圖,文件夾中有三個文件:

②、生成一個發布文件

這一步要使用命令行來完成。

在當前工作目錄移到setup文件所在的文件夾內后,使用命令

            
              py -3 setup.py sdist
            
          

來生成發布文件。發布文件是一個壓縮包,保存在工作路徑下的一個叫disk的文件夾中。

③、安裝發布文件

py3.4包含了一個名為pip的工具,可以用來安裝包。將工作目錄設置為disk后,按下圖輸入命令。

可以看出,已經成功安裝。

需要驗證是否安裝成功,只靠上面的顯示是不行的。要用import來驗證。

【跟著Head First學python】4、代碼重用:函數與模塊_第4張圖片

如圖可以看出,在我把setup文件改好之后,模塊真正安裝成功了。

注意,site-package實際上是一個文件夾,位于...\python\Lib\site-packages,真正安裝好后,會有一個文件夾,名字中帶有安裝的模塊,另外,模塊中函數的源碼也存在該文件夾中,如下:

【跟著Head First學python】4、代碼重用:函數與模塊_第5張圖片

如圖,可以看見vsearch-1.0-py3.7.egg-info文件夾和vsearch.py文件。

3、函數的按值調用與按引用調用

在學C的時候,我們已經清楚了按值調用和按引用調用的區別,這是一個重要考點。

按值調用不會改變函數參數的值,但按引用調用會改變。

在python中,函數既支持按值調用,又支持按引用調用。也就是說,在某些情況下,函數的行為看起來像按值調用,在另外一些情況下,則是按引用調用。其本質則是因為,python中變量都是對象引用,變量中存儲的是值的內存地址,而不是真正的值,從這一點看,所有的變量都是指針。

當變量指向的值是可變的值:列表、字典、集合時,按引用調用來行為;

當變量指向的值是不變的值:字符串、正數、元組時,按值調用來行為。

然而有一點要注意,參見下面兩個函數:

            
              #按值調用
def double(arg):
    print('Before: ',arg)
    arg=arg*2
    print('After: ',arg)
#按引用調用
def change(arg):
    print('Before: ',arg)
    arg.append('More data')
    print('After: ',arg)
            
          

當arg為整數時,調用double函數,參數為a,看上去a會不變,因為a是一個整數,屬于不變的值,應按值調用,實際也是這樣:

但是當arg為一個列表時,按原來的想法,參數為b,是一個列表,列表屬于可變的值,因此b應該翻倍,因為是按引用調用,實際卻不是這樣:

【跟著Head First學python】4、代碼重用:函數與模塊_第6張圖片

可以看出,arg的確翻倍了,但是b沒有翻倍。

這是python中=的特性決定的。

在python中,=是賦值操作,在賦值時,首先執行=右邊的代碼,創建一個新的對象,然后將這個新的對象賦給=左邊的變量。也就是說,在上面的代碼中,是對b的內容進行*2的操作,形成一個新的對象,賦給arg,然而b本身一點變化都沒有。因此b不會變化。

其實還有一個好玩的事,前面說過,python中變量都是指針,那么參見下圖:

【跟著Head First學python】4、代碼重用:函數與模塊_第7張圖片

我們將a初始化為一個整數1,b初始化為2,然后觀察a和b的地址,它們是不同的;

然后將a加1,現在a=2,按C的理解,應該是140734582055568這個地址中的內容從1變成了2,但實際不是這樣,是a指向了b的地址,原因是b=2。這也可以看出,對于不能改變的量,python賦值采用的是改變指向的操作完成的。這也導致了在C中很容易做的數字處理變得麻煩。

4、檢查PEP8的兼容性

若想檢查代碼是否符合PEP8的規范,需要使用pytest框架和pep8插件。同樣的,我們使用pip進行安裝。

按如下執行代碼:

【跟著Head First學python】4、代碼重用:函數與模塊_第8張圖片

如下圖表示安裝成功。

【跟著Head First學python】4、代碼重用:函數與模塊_第9張圖片

接下來按照同樣方法安裝pep8。

安裝成功之后,前往需要檢查的代碼文件所在的文件夾,此處就是vsearch.py所在的文件夾,執行如下命令:

            
              py.test --pep8 vsearch.py
            
          

效果如下:

【跟著Head First學python】4、代碼重用:函數與模塊_第10張圖片

可以看出,有五處不合格,三處是代碼中間的冒號:后面沒有加空格,一處是逗號,后面沒有加空格,一處是等號=左右沒有加空格。更改。然后再次檢查。如下:

【跟著Head First學python】4、代碼重用:函數與模塊_第11張圖片

右側的100%和1 passed說明已經沒有錯誤。

?


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久国产精品2020盗摄 | 一区二区三区在线 | 日本 | 天天摸天天操 | 免费在线激情视频 | 天堂精品在线 | 成人精品一区二区三区校园激情 | 青青青青久久精品国产一百度 | 99热久久这里只有精品6 | 亚洲色图国产精品 | 中文国产欧美在线观看 | 国产 日韩 一区 | 五月天激情亚洲婷婷在线 | 亚洲乱码一区二区三区国产精品 | 国产亚洲欧美日韩综合综合二区 | 久久国产精品永久免费网站 | 天天操天天插天天射 | 欧美一级级a在线观看 | 成年女人视频免费观看一 | 日日摸日日碰夜夜97 | 天天摸天天干天天操 | 99热这里只有免费国产精品 | 黄色毛片在线播放 | 欧美一级在线毛片免费观看 | 亚洲精品成人一区 | 亚洲一二三区在线观看 | 久草日韩 | 国产精品66在线观看 | 国产大片91精品免费观看不卡 | 国产 欧美 在线 | 99久久免费精品国产免费高清 | 亚洲综合精品香蕉久久网 | 欧美日韩国产在线人成 | 亚洲欧美成人网 | 亚洲欧美亚洲 | 久久婷婷色综合老司机 | 手机观看毛片 | 欧美专区综合 | 国内精品久久久久丫网址 | 视频二区 中文字幕 欧美 | 日韩欧美手机在线 | 国产成人免费不卡在线观看 |