摘要:程序用于在編程社群的成員之間交流這些想法。在編程中,我們處理兩種元素函數和數據。在中,我們可以使用賦值語句來建立新的綁定,它包含左邊的名稱和右邊的值。例如,它并不能處理賦值語句。這些圖解的必要部分是函數的表示。
1.2 編程元素
來源:1.2 The Elements of Programming
譯者:飛龍
協議:CC BY-NC-SA 4.0
編程語言是操作計算機來執行任務的手段,它也在我們組織關于過程的想法中,作為一種框架。程序用于在編程社群的成員之間交流這些想法。所以,程序必須為人類閱讀而編寫,并且僅僅碰巧可以讓機器執行。
當我們描述一種語言時,我們應該特別注意這種語言的手段,來將簡單的想法組合為更復雜的想法。每個強大的語言都擁有用于完成下列任務的機制:
基本的表達式和語句,它們由語言提供,表示最簡單的構建代碼塊。
組合的手段,復雜的元素由簡單的元素通過它來構建,以及
抽象的手段,復雜的元素可以通過它來命名,以及作為整體來操作。
在編程中,我們處理兩種元素:函數和數據。(不久之后我們就會探索它們并不是真的非常不同。)不正式地說,數據是我們想要操作的東西,函數描述了操作數據的規則。所以,任何強大的編程語言都應該能描述基本數據和基本函數,并且應該擁有組合和抽象二者的方式。
1.2.1 表達式在實驗 Python 解釋器之后,我們現在必須重新開始,按照順序一步步地探索 Python 語言。如果示例看上去很簡單,要有耐心 -- 更刺激的東西還在后面。
我們以基本表達式作為開始。一種基本表達式就是數值。更精確地說,是你鍵入的,由 10 進制數字表示的數值組成的表達式。
>>> 42 42
表達式表示的數值也許會和算數運算符組合,來形成復合表達式,解釋器會求出它:
>>> -1 - -1 0 >>> 1/2 + 1/4 + 1/8 + 1/16 + 1/32 + 1/64 + 1/128 0.9921875
這些算術表達式使用了中綴符號,其中運算符(例如+、-、*、/)出現在操作數(數值)中間。Python包含許多方法來形成復合表達式。我們不會嘗試立即將它們列舉出來,而是在進行中介紹新的表達式形式,以及它們支持的語言特性。
1.2.2 調用表達式最重要的復合表達式就是調用表達式,它在一些參數上調用函數?;貞洿鷶抵?,函數的數學概念是一些輸入值到輸出值的映射。例如,max函數將它的輸入映射到單個輸出,輸出是輸入中的最大值。Python 中的函數不僅僅是輸入輸出的映射,它表述了計算過程。但是,Python 表示函數的方式和數學中相同。
>>> max(7.5, 9.5) 9.5
調用表達式擁有子表達式:運算符在圓括號之前,圓括號包含逗號分隔的操作數。運算符必須是個函數,操作數可以是任何值。這里它們都是數值。當求解這個調用表達式時,我們說max函數以參數 7.5 和 9.5 調用,并且返回 9.5。
調用表達式中的參數的順序極其重要。例如,函數pow計算第一個參數的第二個參數次方。
>>> pow(100, 2) 10000 >>> pow(2, 100) 1267650600228229401496703205376
函數符號比中綴符號的數學慣例有很多優點。首先,函數可以接受任何數量的參數:
>>> max(1, -2, 3, -4) 3
不會產生任何歧義,因為函數的名稱永遠在參數前面。
其次,函數符號可以以直接的方式擴展為嵌套表達式,其中元素本身是復合表達式。在嵌套的調用表達式中,不像嵌套的中綴表達式,嵌套結構在圓括號中非常明顯。
>>> max(min(1, -2), min(pow(3, 5), -4)) -2
(理論上)這種嵌套沒有任何限制,并且 Python 解釋器可以解釋任何復雜的表達式。然而,人們可能會被多級嵌套搞暈。你作為程序員的一個重要作用就是構造你自己、你的同伴以及其它在未來可能會閱讀你代碼的人可以解釋的表達式。
最后,數學符號在形式上多種多樣:星號表示乘法,上標表示乘方,橫杠表示除法,屋頂和側壁表示開方。這些符號中一些非常難以打出來。但是,所有這些復雜事物可以通過調用表達式的符號來統一。雖然 Python 通過中綴符號(比如+和-)支持常見的數學運算符,任何運算符都可以表示為帶有名字的函數。
1.2.3 導入庫函數Python 定義了大量的函數,包括上一節提到的運算符函數,但是通常不能使用它們的名字,這樣做是為了避免混亂。反之,它將已知的函數和其它東西組織在模塊中,這些模塊組成了 Python 庫。需要導入它們來使用這些元素。例如,math模塊提供了大量的常用數學函數:
>>> from math import sqrt, exp >>> sqrt(256) 16.0 >>> exp(1) 2.718281828459045
operator模塊提供了中綴運算符對應的函數:
>>> from operator import add, sub, mul >>> add(14, 28) 42 >>> sub(100, mul(7, add(8, 4))) 16
import語句標明了模塊名稱(例如operator或math),之后列出被導入模塊的具名屬性(例如sqrt和exp)。
Python 3 庫文檔列出了定義在每個模塊中的函數,例如數學模塊。然而,這個文檔為了解整個語言的開發者編寫。到現在為止,你可能發現使用函數做實驗會比閱讀文檔告訴你更多它的行為。當你更熟悉 Python 語言和詞匯時,這個文檔就變成了一份有價值的參考來源。
1.2.4 名稱和環境編程語言的要素之一是它提供的手段,用于使用名稱來引用計算對象。如果一個值被給予了名稱,我們就說這個名稱綁定到了值上面。
在 Python 中,我們可以使用賦值語句來建立新的綁定,它包含=左邊的名稱和右邊的值。
>>> radius = 10 >>> radius 10 >>> 2 * radius 20
名稱也可以通過import語句綁定:
>>> from math import pi >>> pi * 71 / 223 1.0002380197528042
我們也可以在一個語句中將多個值賦給多個名稱,其中名稱和表達式由逗號分隔:
>>> area, circumference = pi * radius * radius, 2 * pi * radius >>> area 314.1592653589793 >>> circumference 62.83185307179586
=符號在 Python(以及許多其它語言)中叫做賦值運算符。賦值是 Python 中的最簡單的抽象手段,因為它使我們可以使用最簡單的名稱來引用復合操作的結果,例如上面計算的area。這樣,復雜的程序可以由復雜性遞增的計算對象一步一步構建,
將名稱綁定到值上,以及隨后通過名稱來檢索這些值的可能,意味著解釋器必須維護某種內存來跟蹤這些名稱和值的綁定。這些內存叫做環境。
名稱也可以綁定到函數。例如,名稱max綁定到了我們曾經用過的max函數上。函數不像數值,不易于渲染成文本,所以 Python 使用識別描述來代替,當我們打印函數時:
>>> max
我們可以使用賦值運算符來給現有函數起新的名字:
>>> f = max >>> f>>> f(3, 4) 4
成功的賦值語句可以將名稱綁定到新的值:
>>> f = 2 >>> f 2
在 Python 中,通過賦值綁定的名稱通常叫做變量名稱,因為它們在執行程序期間可以綁定到許多不同的值上面。
1.2.5 嵌套表達式的求解我們這章的目標之一是隔離程序化思考相關的問題。作為一個例子,考慮嵌套表達式的求解,解釋器自己會遵循一個過程:
為了求出調用表達式,Python 會執行下列事情:
求出運算符和操作數子表達式,之后
在值為操作數子表達式的參數上調用值為運算符子表達式的函數。
這個簡單的過程大體上展示了一些過程上的重點。第一步表明為了完成調用表達式的求值過程,我們首先必須求出其它表達式。所以,求值過程本質上是遞歸的,也就是說,它會調用其自身作為步驟之一。
例如,求出
>>> mul(add(2, mul(4, 6)), add(3, 5)) 208
需要應用四次求值過程。如果我們將每個需要求解的表達式抽出來,我們可以可視化這一過程的層次結構:
這個示例叫做表達式樹。在計算機科學中,樹從頂端向下生長。每一點上的對象叫做節點。這里它們是表達式和它們的值。
求出根節點,也就是整個表達式,需要首先求出枝干節點,也就是子表達式。葉子節點(也就是沒有子節點的節點)的表達式表示函數或數值。內部節點分為兩部分:表示我們想要應用的求值規則的調用表達式,以及表達式的結果。觀察這棵樹中的求值,我們可以想象操作數的值向上流動,從葉子節點開始,在更高的層上融合。
接下來,觀察第一步的重復應用,這會將我們帶到需要求值的地方,并不是調用表達式,而是基本表達式,例如數字(比如2),以及名稱(比如add),我們需要規定下列事物來謹慎對待基本的東西:
數字求值為它標明的數值,
名稱求值為當前環境中這個名稱所關聯的值
要注意環境的關鍵作用是決定表達式中符號的含義。Python 中,在不指定任何環境信息,來提供名稱x(以及名稱add)的含義的情況下,談到這樣一個表達式的值沒有意義:
>>> add(x, 1)
環境提供了求值所發生的上下文,它在我們理解程序執行中起到重要作用。
這個求值過程并不符合所有 Python 代碼的求解,僅僅是調用表達式、數字和名稱。例如,它并不能處理賦值語句。
>>> x = 3
的執行并不返回任何值,也不求解任何參數上的函數,因為賦值的目的是將一個名稱綁定到一個值上。通常,語句不會被求值,而是被執行,它們不產生值,但是會改變一些東西。每種語句或表達式都有自己的求值或執行過程,我們會在涉及時逐步介紹。
注:當我們說“數字求值為數值”的時候,我們的實際意思是 Python 解釋器將數字求解為數值。Python 的解釋器使編程語言具有了這個意義。假設解釋器是一個固定的程序,行為總是一致,我們就可以說數字(以及表達式)自己在 Python 程序的上下文中會求解為值。
1.2.6 函數圖解當我們繼續構建求值的正式模型時,我們會發現解釋器內部狀態的圖解有助于我們跟蹤求值過程的發展。這些圖解的必要部分是函數的表示。
純函數:具有一些輸入(參數)以及返回一些輸出(調用結果)的函數。內建函數
>>> abs(-2) 2
可以描述為接受輸入并產生輸出的小型機器。
abs是純函數。純函數具有一個特性,調用它們時除了返回一個值之外沒有其它效果。
非純函數:除了返回一個值之外,調用非純函數會產生副作用,這會改變解釋器或計算機的一些狀態。一個普遍的副作用就是在返回值之外生成額外的輸出,例如使用print函數:
>>> print(-2) -2 >>> print(1, 2, 3) 1 2 3
雖然這些例子中的print和abs看起來很像,但它們本質上以不同方式工作。print的返回值永遠是None,它是一個 Python 特殊值,表示沒有任何東西。Python 交互式解釋器并不會自動打印None值。這里,print自己打印了輸出,作為調用中的副作用。
調用print的嵌套表達式會凸顯出它的非純特性:
>>> print(print(1), print(2)) 1 2 None None
如果你發現自己不能預料到這個輸出,畫出表達式樹來弄清為什么這個表達式的求值會產生奇怪的輸出。
要當心print!它的返回值為None,意味著它不應該在賦值語句中用作表達式:
>>> two = print(2) 2 >>> print(two) None
簽名:不同函數具有不同的允許接受的參數數量。為了跟蹤這些必備條件,我們需要以一種展示函數名稱和參數名稱的方式,畫出每個函數。abs函數值接受一個叫作number的參數,向它提供更多或更少的參數會產生錯誤。print函數可以接受任意數量的參數,所以它渲染為print(...)。函數的可接受參數的描述叫做函數的簽名。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/38101.html
摘要:為通用語言設計解釋器的想法可能令人畏懼。但是,典型的解釋器擁有簡潔的通用結構兩個可變的遞歸函數,第一個求解環境中的表達式,第二個在參數上調用函數。這一章接下來的兩節專注于遞歸函數和數據結構,它們是理解解釋器設計的基礎。 3.1 引言 來源:3.1 Introduction 譯者:飛龍 協議:CC BY-NC-SA 4.0 第一章和第二章描述了編程的兩個基本元素:數據和函數之間的...
摘要:另一個賦值語句將名稱關聯到出現在莎士比亞劇本中的所有去重詞匯的集合,總計個。表達式是一個復合表達式,計算出正序或倒序出現的莎士比亞詞匯集合。在意圖上并沒有按照莎士比亞或者回文來設計,但是它極大的靈活性讓我們用極少的代碼處理大量文本。 1.1 引言 來源:1.1 Introduction 譯者:飛龍 協議:CC BY-NC-SA 4.0 計算機科學是一個極其寬泛的學科。全球的分布...
摘要:示例有理數的算術有理數可表示為整數的比值,并且它組成了實數的一個重要子類。有理數的值需要兩部分來描述。這里的重要概念是,通過將有理數表示為整數的比值,我們能夠完全避免近似問題。返回有理數的分子。 2.2 數據抽象 來源:2.2 Data Abstraction 譯者:飛龍 協議:CC BY-NC-SA 4.0 由于我們希望在程序中表達世界中的大量事物,我們發現它們的大多數都具有...
摘要:對象表示信息,但是同時和它們所表示的抽象概念行為一致。通過綁定行為和信息,對象提供了可靠獨立的日期抽象。名稱來源于實數在中表示的方式浮點表示。另一方面,對象可以表示很大范圍內的分數,但是不能表示所有有理數。 2.1 引言 來源:2.1 Introduction 譯者:飛龍 協議:CC BY-NC-SA 4.0 在第一章中,我們專注于計算過程,以及程序設計中函數的作用。我們看到了...
摘要:以這種方式實現對象系統的目的是展示使用對象隱喻并不需要特殊的編程語言。我們的實現并不遵循類型系統的明確規定。反之,它為實現對象隱喻的核心功能而設計。是分發字典,它響應消息和。 2.6 實現類和對象 來源:2.6 Implementing Classes and Objects 譯者:飛龍 協議:CC BY-NC-SA 4.0 在使用面向對象編程范式時,我們使用對象隱喻來指導程序...
閱讀 3246·2021-11-23 10:09
閱讀 2066·2021-10-26 09:51
閱讀 981·2021-10-09 09:44
閱讀 3909·2021-10-08 10:04
閱讀 2748·2021-09-22 15:14
閱讀 3627·2021-09-22 15:02
閱讀 1062·2021-08-24 10:03
閱讀 1730·2019-12-27 12:14