成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

SICP Python 描述 1.5 控制

mingzhong / 1165人閱讀

摘要:函數(shù)體由表達式組成。我們說頭部控制語句組。于是,函數(shù)體內的賦值語句不會影響全局幀。包含了多種假值,包括和布爾值。布爾值表示了邏輯表達式中的真值。執(zhí)行測試以及返回布爾值的函數(shù)通常以開頭,并不帶下劃線例如等等。返回值之后會和預期結果進行比對。

1.5 控制

來源:1.5 Control

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

我們現(xiàn)在可以定義的函數(shù)能力有限,因為我們還不知道一種方法來進行測試,并且根據(jù)測試結果來執(zhí)行不同的操作。控制語句可以讓我們完成這件事。它們不像嚴格的求值子表達式那樣從左向右編寫,并且可以從它們控制解釋器下一步做什么當中得到它們的名稱。這可能基于表達式的值。

1.5.1 語句

目前為止,我們已經(jīng)初步思考了如何求出表達式。然而,我們已經(jīng)看到了三種語句:賦值、defreturn語句。這些 Python 代碼并不是表達式,雖然它們中的一部分是表達式。

要強調的是,語句的值是不相干的(或不存在的),我們使用執(zhí)行而不是求值來描述語句。
每個語句都描述了對解釋器狀態(tài)的一些改變,執(zhí)行語句會應用這些改變。像我們之前看到的return和賦值語句那樣,語句的執(zhí)行涉及到求解所包含的子表達式。

表達式也可以作為語句執(zhí)行,其中它們會被求值,但是它們的值會舍棄。執(zhí)行純函數(shù)沒有什么副作用,但是執(zhí)行非純函數(shù)會產生效果作為函數(shù)調用的結果。

考慮下面這個例子:

>>> def square(x):
        mul(x, x) # Watch out! This call doesn"t return a value.

這是有效的 Python 代碼,但是并不是想表達的意思。函數(shù)體由表達式組成。表達式本身是個有效的語句,但是語句的效果是,mul函數(shù)被調用了,然后結果被舍棄了。如果你希望對表達式的結果做一些事情,你需要這樣做:使用賦值語句來儲存它,或者使用return語句將它返回:

>>> def square(x):
        return mul(x, x)

有時編寫一個函數(shù)體是表達式的函數(shù)是有意義的,例如調用類似print的非純函數(shù):

>>> def print_square(x):
        print(square(x))

在最高層級上,Python 解釋器的工作就是執(zhí)行由語句組成的程序。但是,許多有意思的計算工作來源于求解表達式。語句管理程序中不同表達式之間的關系,以及它們的結果會怎么樣。

1.5.2 復合語句

通常,Python 的代碼是語句的序列。一條簡單的語句是一行不以分號結束的代碼。復合語句之所以這么命名,因為它是其它(簡單或復合)語句的復合。復合語句一般占據(jù)多行,并且以一行以冒號結尾的頭部開始,它標識了語句的類型。同時,一個頭部和一組縮進的代碼叫做子句(或從句)。復合語句由一個或多個子句組成。

: ... : ... ...

我們可以這樣理解我們已經(jīng)見到的語句:

表達式、返回語句和賦值語句都是簡單語句。

def語句是復合語句。def頭部之后的組定義了函數(shù)體。

為每種頭部特化的求值規(guī)則指導了組內的語句什么時候以及是否會被執(zhí)行。我們說頭部控制語句組。例如,在def語句的例子中,我們看到返回表達式并不會立即求值,而是儲存起來用于以后的使用,當所定義的函數(shù)最終調用時就會求值。

我們現(xiàn)在也能理解多行的程序了。

執(zhí)行語句序列需要執(zhí)行第一條語句。如果這個語句不是重定向控制,之后執(zhí)行語句序列的剩余部分,如果存在的話。

這個定義揭示出遞歸定義“序列”的基本結構:一個序列可以劃分為它的第一個元素和其余元素。語句序列的“剩余”部分也是一個語句序列。所以我們可以遞歸應用這個執(zhí)行規(guī)則。這個序列作為遞歸數(shù)據(jù)結構的看法會在隨后的章節(jié)中再次出現(xiàn)。

這一規(guī)則的重要結果就是語句順序執(zhí)行,但是隨后的語句可能永遠不會執(zhí)行到,因為有重定向控制。

實踐指南:在縮進代碼組時,所有行必須以相同數(shù)量以及相同方式縮進(空格而不是Tab)。任何縮進的變動都會導致錯誤。

1.5.3 定義函數(shù) II:局部賦值

一開始我們說,用戶定義函數(shù)的函數(shù)體只由帶有一個返回表達式的一個返回語句組成。實際上,函數(shù)可以定義為操作的序列,不僅僅是一條表達式。Python 復合語句的結構自然讓我們將函數(shù)體的概念擴展為多個語句。

無論用戶定義的函數(shù)何時被調用,定義中的子句序列在局部環(huán)境內執(zhí)行。return語句會重定向控制:無論什么時候執(zhí)行return語句,函數(shù)調用的流程都會中止,返回表達式的值會作為被調用函數(shù)的返回值。

于是,賦值語句現(xiàn)在可以出現(xiàn)在函數(shù)體中。例如,這個函數(shù)以第一個數(shù)的百分數(shù)形式,返回兩個數(shù)量的絕對值,并使用了兩步運算:

>>> def percent_difference(x, y):
        difference = abs(x-y)
        return 100 * difference / x
>>> percent_difference(40, 50)
25.0

賦值語句的效果是在當前環(huán)境的第一個幀上,將名字綁定到值上。于是,函數(shù)體內的賦值語句不會影響全局幀。函數(shù)只能操作局部作用域的現(xiàn)象是創(chuàng)建模塊化程序的關鍵,其中純函數(shù)只通過它們接受和返回的值與外界交互。

當然,percent_difference函數(shù)也可以寫成一個表達式,就像下面這樣,但是返回表達式會更加復雜:

>>> def percent_difference(x, y):
        return 100 * abs(x-y) / x

目前為止,局部賦值并不會增加函數(shù)定義的表現(xiàn)力。當它和控制語句組合時,才會這樣。此外,局部賦值也可以將名稱賦為間接量,在理清復雜表達式的含義時起到關鍵作用。

新的環(huán)境特性:局部賦值。

1.5.4 條件語句

Python 擁有內建的絕對值函數(shù):

>>> abs(-2)
2

我們希望自己能夠實現(xiàn)這個函數(shù),但是我們當前不能直接定義函數(shù)來執(zhí)行測試并做出選擇。我們希望表達出,如果x是正的,abs(x)返回x,如果x是 0,abx(x)返回 0,否則abs(x)返回-x。Python 中,我們可以使用條件語句來表達這種選擇。

>>> def absolute_value(x):
        """Compute abs(x)."""
        if x > 0:
            return x
        elif x == 0:
            return 0
        else:
            return -x
            
>>> absolute_value(-2) == abs(-2)
True

absolute_value的實現(xiàn)展示了一些重要的事情:

條件語句。Python 中的條件語句包含一系列的頭部和語句組:一個必要的if子句,可選的elif子句序列,和最后可選的else子句:

if :
    
elif :
    
else:
    

當執(zhí)行條件語句時,每個子句都按順序處理:

求出頭部中的表達式。

如果它為真,執(zhí)行語句組。之后,跳過條件語句中隨后的所有子句。

如果能到達else子句(僅當所有ifelif表達式值為假時),它的語句組才會被執(zhí)行。

布爾上下文。上面過程的執(zhí)行提到了“假值”和“真值”。條件塊頭部語句中的表達式也叫作布爾上下文:它們值的真假對控制流很重要,但在另一方面,它們的值永遠不會被賦值或返回。Python 包含了多種假值,包括 0、None和布爾值False。所有其他數(shù)值都是真值。在第二章中,我們就會看到每個 Python 中的原始數(shù)據(jù)類型都是真值或假值。

布爾值。Python 有兩種布爾值,叫做TrueFalse。布爾值表示了邏輯表達式中的真值。內建的比較運算符,>、<、>=、<=、==!=,返回這些值。

>>> 4 < 2
False
>>> 5 >= 5
True

第二個例子讀作“5 大于等于 5”,對應operator模塊中的函數(shù)ge。

>>> 0 == -0
True

最后的例子讀作“0 等于 -0”,對應operator模塊的eq函數(shù)。要注意 Python 區(qū)分賦值(=)和相等測試(==)。許多語言中都有這個慣例。

布爾運算符。Python 也內建了三個基本的邏輯運算符:

>>> True and False
False
>>> True or False
True
>>> not False
True

邏輯表達式擁有對應的求值過程。這些過程揭示了邏輯表達式的真值有時可以不執(zhí)行全部子表達式而確定,這個特性叫做短路。

為了求出表達式 and

求出子表達式。

如果結果v是假值,那么表達式求值為v。

否則表達式的值為子表達式

為了求出表達式 or

求出子表達式。

如果結果v是真值,那么表達式求值為v

否則表達式的值為子表達式。

為了求出表達式not

求出,如果值是True那么返回值是假值,如果為False則反之。

這些值、規(guī)則和運算符向我們提供了一種組合測試結果的方式。執(zhí)行測試以及返回布爾值的函數(shù)通常以is開頭,并不帶下劃線(例如isfinite、isdigit、isinstance等等)。

1.5.5 迭代

除了選擇要執(zhí)行的語句,控制語句還用于表達重復操作。如果我們編寫的每一行代碼都只執(zhí)行一次,程序會變得非常沒有生產力。只有通過語句的重復執(zhí)行,我們才可以釋放計算機的潛力,使我們更加強大。我們已經(jīng)看到了重復的一種形式:一個函數(shù)可以多次調用,雖然它只定義一次。迭代控制結構是另一種將相同語句執(zhí)行多次的機制。

考慮斐波那契數(shù)列,其中每個數(shù)值都是前兩個的和:

0, 1, 1, 2, 3, 5, 8, 13, 21, ...

每個值都通過重復使用“前兩個值的和”的規(guī)則構造。為了構造第 n 個值,我們需要跟蹤我們創(chuàng)建了多少個值(k),以及第 k 個值(curr)和它的上一個值(pred),像這樣:

>>> def fib(n):
        """Compute the nth Fibonacci number, for n >= 2."""
        pred, curr = 0, 1   # Fibonacci numbers
        k = 2               # Position of curr in the sequence
        while k < n:
            pred, curr = curr, pred + curr  # Re-bind pred and curr
            k = k + 1                       # Re-bind k
        return curr
>>> fib(8)
13

要記住逗號在賦值語句中分隔了多個名稱和值。這一行:

pred, curr = curr, pred + curr

具有將curr的值重新綁定到名稱pred上,以及將pred + curr的值重新綁定到curr上的效果。所有=右邊的表達式會在綁定發(fā)生之前求出來。

while子句包含一個頭部表達式,之后是語句組:

while :
    

為了執(zhí)行while子句:

求出頭部表達式。

如果它為真,執(zhí)行語句組,之后返回到步驟 1。

在步驟 2 中,整個while子句的語句組在頭部表達式再次求值之前被執(zhí)行。

為了防止while子句的語句組無限執(zhí)行,它應該總是在每次通過時修改環(huán)境的狀態(tài)。

不終止的while語句叫做無限循環(huán)。按下-C可以強制讓 Python 停止循環(huán)。

1.5.6 實踐指南:測試

函數(shù)的測試是驗證函數(shù)的行為是否符合預期的操作。我們的函數(shù)現(xiàn)在已經(jīng)足夠復雜了,我們需要開始測試我們的實現(xiàn)。

測試是系統(tǒng)化執(zhí)行這個驗證的機制。測試通常寫為另一個函數(shù),這個函數(shù)包含一個或多個被測函數(shù)的樣例調用。返回值之后會和預期結果進行比對。不像大多數(shù)通用的函數(shù),測試涉及到挑選特殊的參數(shù)值,并使用它來驗證調用。測試也可作為文檔:它們展示了如何調用函數(shù),以及什么參數(shù)值是合理的。

要注意我們也將“測試”這個詞用于ifwhile語句的頭部中作為一種技術術語。當我們將“測試”這個詞用作表達式,或者用作一種驗證機制時,它應該在語境中十分明顯。

斷言。程序員使用assert語句來驗證預期,例如測試函數(shù)的輸出。assert語句在布爾上下文中只有一個表達式,后面是帶引號的一行文本(單引號或雙引號都可以,但是要一致)如果表達式求值為假,它就會顯示。

>>> assert fib(8) == 13, "The 8th Fibonacci number should be 13"

當被斷言的表達式求值為真時,斷言語句的執(zhí)行沒有任何效果。當它是假時,asset會造成執(zhí)行中斷。

fib編寫的test函數(shù)測試了幾個參數(shù),包含n的極限值:

>>> def fib_test():
        assert fib(2) == 1, "The 2nd Fibonacci number should be 1"
        assert fib(3) == 1, "The 3nd Fibonacci number should be 1"
        assert fib(50) == 7778742049, "Error at the 50th Fibonacci number"

在文件中而不是直接在解釋器中編寫 Python 時,測試可以寫在同一個文件,或者后綴為_test.py的相鄰文件中。

Doctest。Python 提供了一個便利的方法,將簡單的測試直接寫到函數(shù)的文檔字符串內。文檔字符串的第一行應該包含單行的函數(shù)描述,后面是一個空行。參數(shù)和行為的詳細描述可以跟隨在后面。此外,文檔字符串可以包含調用該函數(shù)的簡單交互式會話:

>>> def sum_naturals(n):
        """Return the sum of the first n natural numbers

        >>> sum_naturals(10)
        55
        >>> sum_naturals(100)
        5050
        """
        total, k = 0, 1
        while k <= n:
          total, k = total + k, k + 1
        return total

之后,可以使用 doctest 模塊來驗證交互。下面的globals函數(shù)返回全局變量的表示,解釋器需要它來求解表達式。

>>> from doctest import run_docstring_examples
>>> run_docstring_examples(sum_naturals, globals())

在文件中編寫 Python 時,可以通過以下面的命令行選項啟動 Python 來運行一個文檔中的所有 doctest。

python3 -m doctest 

高效測試的關鍵是在實現(xiàn)新的函數(shù)之后(甚至是之前)立即編寫(以及執(zhí)行)測試。只調用一個函數(shù)的測試叫做單元測試。詳盡的單元測試是良好程序設計的標志。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/45498.html

相關文章

  • SICP Python 描述 第二章 使用對象構建抽象 2.1 引言

    摘要:對象表示信息,但是同時和它們所表示的抽象概念行為一致。通過綁定行為和信息,對象提供了可靠獨立的日期抽象。名稱來源于實數(shù)在中表示的方式浮點表示。另一方面,對象可以表示很大范圍內的分數(shù),但是不能表示所有有理數(shù)。 2.1 引言 來源:2.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 在第一章中,我們專注于計算過程,以及程序設計中函數(shù)的作用。我們看到了...

    phoenixsky 評論0 收藏0
  • SICP Python 描述 第三章 計算機程序的構造和解釋 3.1 引言

    摘要:為通用語言設計解釋器的想法可能令人畏懼。但是,典型的解釋器擁有簡潔的通用結構兩個可變的遞歸函數(shù),第一個求解環(huán)境中的表達式,第二個在參數(shù)上調用函數(shù)。這一章接下來的兩節(jié)專注于遞歸函數(shù)和數(shù)據(jù)結構,它們是理解解釋器設計的基礎。 3.1 引言 來源:3.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 第一章和第二章描述了編程的兩個基本元素:數(shù)據(jù)和函數(shù)之間的...

    v1 評論0 收藏0
  • SICP Python 描述 2.7 泛用方法

    摘要:使用消息傳遞,我們就能使抽象數(shù)據(jù)類型直接擁有行為。構造器以類似的方式實現(xiàn)它在參數(shù)上調用了叫做的方法。抽象數(shù)據(jù)類型允許我們在數(shù)據(jù)表示和用于操作數(shù)據(jù)的函數(shù)之間構造界限。 2.7 泛用方法 來源:2.7 Generic Operations 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 這一章中我們引入了復合數(shù)據(jù)類型,以及由構造器和選擇器實現(xiàn)的數(shù)據(jù)抽象機制。使用消息傳遞,我們就能...

    leanote 評論0 收藏0
  • SICP Python 描述 3.4 異常

    摘要:的最常見的作用是構造異常實例并拋出它。子句組只在執(zhí)行過程中的異常產生時執(zhí)行。每個子句指定了需要處理的異常的特定類。將強制轉為字符串會得到由返回的人類可讀的字符串。 3.4 異常 來源:3.4 Exceptions 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 程序員必須總是留意程序中可能出現(xiàn)的錯誤。例子數(shù)不勝數(shù):一個函數(shù)可能不會收到它預期的信息,必需的資源可能會丟失,或者網(wǎng)...

    pkhope 評論0 收藏0
  • SICP Python描述 1.1 引言

    摘要:另一個賦值語句將名稱關聯(lián)到出現(xiàn)在莎士比亞劇本中的所有去重詞匯的集合,總計個。表達式是一個復合表達式,計算出正序或倒序出現(xiàn)的莎士比亞詞匯集合。在意圖上并沒有按照莎士比亞或者回文來設計,但是它極大的靈活性讓我們用極少的代碼處理大量文本。 1.1 引言 來源:1.1 Introduction 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 計算機科學是一個極其寬泛的學科。全球的分布...

    xumenger 評論0 收藏0

發(fā)表評論

0條評論

mingzhong

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<