黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

【跟著Head First學(xué)python】4、代碼重用:函數(shù)與模塊

系統(tǒng) 2029 0

1、函數(shù)

相比于C++,python中寫一個(gè)函數(shù)需要一個(gè)關(guān)鍵字def。其主要結(jié)構(gòu)如下:

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

如果一個(gè)函數(shù)是一個(gè)類的一部分,它就稱為一個(gè)方法。

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

函數(shù)注解是py3新增的一項(xiàng)功能,類似注釋,它們只負(fù)責(zé)提高程序的可讀性,而不會(huì)對(duì)程序功能做出任何改變。

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

            
              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學(xué)python】4、代碼重用:函數(shù)與模塊_第1張圖片

可以看得出來,犯了很多愚蠢的錯(cuò)誤。首先,最重要的是,雖然沒有為函數(shù)的參數(shù)指定類型,但函數(shù)參數(shù)必須有類型,像我第一次那樣,參數(shù)直接是chy是肯定不行的,單獨(dú)的chy會(huì)被編譯器認(rèn)為是一個(gè)變量而不是一個(gè)字符串;另外,第二次沒有輸入?yún)?shù),會(huì)報(bào)缺少參數(shù)的錯(cuò)誤,第三次直接把函數(shù)名打錯(cuò)了,最后一次,加了單引號(hào),得到正確結(jié)果。

在python中,每一個(gè)對(duì)象都有一個(gè)與之關(guān)聯(lián)的真值,表示這個(gè)對(duì)象為True或者False。如果該對(duì)象計(jì)算為0、值為None、是一個(gè)空串或一個(gè)空的數(shù)據(jù)結(jié)構(gòu),那么就是False,否則是True。使用函數(shù)bool來計(jì)算對(duì)象的真值。嚴(yán)格來說,所有的非空數(shù)據(jù)結(jié)構(gòu)都計(jì)算為True。

默認(rèn)來說,函數(shù)使用return關(guān)鍵字來返回值,只能返回一個(gè)值,若想返回多個(gè)值,就需要使用數(shù)據(jù)結(jié)構(gòu),這和C++中類似。

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

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

            
          

效果如下:

注意,當(dāng)word中不含元音時(shí),應(yīng)該返回一個(gè)空集合。由于集合使用{}包圍,那么空集合應(yīng)該返回{}。但是返回的是set()。這是因?yàn)椋瑊}沒法區(qū)分是空集合還是空字典,因此用{}表示空字典,用set()表示空集合。

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

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

在運(yùn)行時(shí),加不加注解沒有任何區(qū)別,只有在使用help時(shí)有區(qū)別:

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

help會(huì)把注解顯示,還會(huì)把docstring也顯示。

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

            
              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))
            
          

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

如何實(shí)現(xiàn)呢?很簡(jiǎn)單,在參數(shù)注解的后面加入默認(rèn)值即可,如下:

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

這樣,當(dāng)我們?cè)谡{(diào)用search4letters函數(shù)時(shí),若只用了一個(gè)參數(shù),那么就默認(rèn)第二個(gè)參數(shù)是aeiou;若用了兩個(gè)參數(shù),那么letters就不再是默認(rèn)值。默認(rèn)值與初值不同,不要搞混。默認(rèn)值只有在def行才能修改。

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

2、模塊

好,既然在1中,我們已經(jīng)寫好了函數(shù),那么,如何實(shí)現(xiàn)它的可重用呢?

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

我們已經(jīng)知道了,import是用來引入模塊的,也就是說,已經(jīng)有了函數(shù),還要把它打包成一個(gè)模塊,才能在其他文件中調(diào)用這個(gè)函數(shù)。

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

使用import A引入一個(gè)名為A的模塊,編譯器會(huì)去三個(gè)地方找這個(gè)叫A的模塊:首先在當(dāng)前工作目錄找,然后去解釋器的site-package找,最后去標(biāo)準(zhǔn)庫位置找。找到了的話,直接引入,沒找到就報(bào)錯(cuò)。

當(dāng)前工作目錄,這個(gè)概念我是在linux中了解到的。在win中,用cmd進(jìn)入命令行

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

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

如果我們import的模塊不在工作目錄中,那就會(huì)報(bào)錯(cuò)。

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

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

①、創(chuàng)建一個(gè)發(fā)布描述

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

            
              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'],
    )

            
          

重要的參數(shù)有兩個(gè),一個(gè)是name,其值是發(fā)布的包的名字;另一個(gè)是py_modules,其值是文件夾中所有py文件的列表。注意,這里py_modules即使填寫錯(cuò)誤,也不會(huì)報(bào)錯(cuò)。我第一次就是把vsearch打成了vresearch導(dǎo)致安裝成功卻import失敗。很是蛋疼。

txt文件可以為空。

如圖,文件夾中有三個(gè)文件:

②、生成一個(gè)發(fā)布文件

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

在當(dāng)前工作目錄移到setup文件所在的文件夾內(nèi)后,使用命令

            
              py -3 setup.py sdist
            
          

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

③、安裝發(fā)布文件

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

可以看出,已經(jīng)成功安裝。

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

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

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

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

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

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

3、函數(shù)的按值調(diào)用與按引用調(diào)用

在學(xué)C的時(shí)候,我們已經(jīng)清楚了按值調(diào)用和按引用調(diào)用的區(qū)別,這是一個(gè)重要考點(diǎn)。

按值調(diào)用不會(huì)改變函數(shù)參數(shù)的值,但按引用調(diào)用會(huì)改變。

在python中,函數(shù)既支持按值調(diào)用,又支持按引用調(diào)用。也就是說,在某些情況下,函數(shù)的行為看起來像按值調(diào)用,在另外一些情況下,則是按引用調(diào)用。其本質(zhì)則是因?yàn)椋琾ython中變量都是對(duì)象引用,變量中存儲(chǔ)的是值的內(nèi)存地址,而不是真正的值,從這一點(diǎn)看,所有的變量都是指針。

當(dāng)變量指向的值是可變的值:列表、字典、集合時(shí),按引用調(diào)用來行為;

當(dāng)變量指向的值是不變的值:字符串、正數(shù)、元組時(shí),按值調(diào)用來行為。

然而有一點(diǎn)要注意,參見下面兩個(gè)函數(shù):

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

當(dāng)arg為整數(shù)時(shí),調(diào)用double函數(shù),參數(shù)為a,看上去a會(huì)不變,因?yàn)閍是一個(gè)整數(shù),屬于不變的值,應(yīng)按值調(diào)用,實(shí)際也是這樣:

但是當(dāng)arg為一個(gè)列表時(shí),按原來的想法,參數(shù)為b,是一個(gè)列表,列表屬于可變的值,因此b應(yīng)該翻倍,因?yàn)槭前匆谜{(diào)用,實(shí)際卻不是這樣:

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

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

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

在python中,=是賦值操作,在賦值時(shí),首先執(zhí)行=右邊的代碼,創(chuàng)建一個(gè)新的對(duì)象,然后將這個(gè)新的對(duì)象賦給=左邊的變量。也就是說,在上面的代碼中,是對(duì)b的內(nèi)容進(jìn)行*2的操作,形成一個(gè)新的對(duì)象,賦給arg,然而b本身一點(diǎn)變化都沒有。因此b不會(huì)變化。

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

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

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

然后將a加1,現(xiàn)在a=2,按C的理解,應(yīng)該是140734582055568這個(gè)地址中的內(nèi)容從1變成了2,但實(shí)際不是這樣,是a指向了b的地址,原因是b=2。這也可以看出,對(duì)于不能改變的量,python賦值采用的是改變指向的操作完成的。這也導(dǎo)致了在C中很容易做的數(shù)字處理變得麻煩。

4、檢查PEP8的兼容性

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

按如下執(zhí)行代碼:

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

如下圖表示安裝成功。

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

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

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

            
              py.test --pep8 vsearch.py
            
          

效果如下:

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

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

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

右側(cè)的100%和1 passed說明已經(jīng)沒有錯(cuò)誤。

?


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論