<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # Chapter 2 內置數據類型 > " Wonder is the foundation of all philosophy, inquiry its progress, ignorance its end. " > — Michel de Montaigne ## 深入 讓我們暫時將 [第一份 Python 程序](your-first-python-program.html) 拋在腦后,來聊一聊數據類型。在 Python 中, [每個值都有一種數據類型](your-first-python-program.html#declaringfunctions),但您并不需要聲明變量的數據類型。那該方式是如何運作的呢?Python 根據每個變量的初始賦值情況分析其類型,并在內部對其進行跟蹤。 Python 有多種內置數據類型。以下是比較重要的一些: 1. **Booleans[布爾型]** 或為 `True[真]` 或為 `False[假]`。 2. **Numbers[數值型]** 可以是 Integers[整數](`1` 和 `2`)、Floats[浮點數](`1.1` 和 `1.2`)、Fractions[分數](`1/2` 和 `2/3`);甚至是 [Complex Number[復數]](http://en.wikipedia.org/wiki/Complex_number)。 3. **Strings[字符串型]** 是 Unicode 字符序列,_例如:_ 一份 HTML 文檔。 4. **Bytes[字節]** 和 **Byte Arrays[字節數組]**, _例如:_ 一份 JPEG 圖像文件。 5. **Lists[列表]** 是值的有序序列。 6. **Tuples[元組]** 是有序而不可變的值序列。 7. **Sets[集合]** 是裝滿無序值的包裹。 8. **Dictionaries[字典]** 是鍵值對的無序包裹。 當然,還有更多的類型。在 Python 中[一切均為對象](your-first-python-program.html#everythingisanobject),因此存在像 _module[模塊]_、 _function[函數]_、 _class[類]_、 _method[方法]_、 _file[文件]_ 甚至 _compiled code[已編譯代碼]_ 這樣的類型。您已經見過這樣一些例子:[模塊的 name](your-first-python-program.html#runningscripts)、 [函數的 `docstrings`](your-first-python-program.html#docstrings) _等等_。將學到的包括 [《類 _與_ 迭代器》](iterators.html) 中的 Classes[類],以及 [《文件》](files.html) 中的 Files[文件]。 Strings[字符串]和 Bytes[字節串]比較重要,也相對復雜,足以開辟獨立章節予以講述。讓我們先看看其它類型。 ## 布爾類型 在布爾類型上下文中,您幾乎可以使用任何表達式。 布爾類型或為真或為假。Python 有兩個被巧妙地命名為 `True` 和 `False` 的常量,可用于對布爾類型的直接賦值。表達式也可以計算為布爾類型的值。在某些地方(如 `if` 語句),Python 所預期的就是一個可計算出布爾類型值的表達式。這些地方稱為 _布爾類型上下文環境_。事實上,可在布爾類型上下文環境中使用任何表達式,而 Python 將試圖判斷其真值。在布爾類型上下文環境中,不同的數據類型對于何值為真、何值為假有著不同的規則。(看過本章稍后的實例后,這一點將更好理解。) 例如,看看 [`humansize.py`](your-first-python-program.html#divingin) 中的這個片段: ``` if size < 0: raise ValueError('number must be non-negative') ``` `size` 是整數, 0 是整數,而 `&lt;` 是數字運算符。`size &lt; 0` 表達式的結果始終是布爾值。可在 Python 交互式 shell 中自行測試下結果: ``` >>> size = 1 >>> size < 0 False >>> size = 0 >>> size < 0 False >>> size = -1 >>> size < 0 True ``` 由于 Python 2 的一些遺留問題,布爾值可以當做數值對待。`True` 為 `1`;`False` 為 0 。 ``` >>> True + True 2 >>> True - False 1 >>> True * False 0 >>> True / False Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: int division or modulo by zero ``` 喔,喔,喔!別那么干。忘掉我剛才說的。 ## 數值類型 數值類型是可畏的。有太多類型可選了。Python 同時支持 Integer[整型] 和 Floating Point[浮點型] 數值。無任何類型聲明可用于區分;Python 通過是否有 小數 點來分辨它們。 ``` <class 'int'> True 2 2.0 >>> type(2.0) <class 'float'> ``` 1. 可以使用 `type()` 函數來檢測任何值或變量的類型。正如所料,`1` 為 `int` 類型。 2. 同樣,還可使用 `isinstance()` 函數判斷某個值或變量是否為給定某個類型。 3. 將一個 `int` 與一個 `int` 相加將得到一個 `int` 。 4. 將一個 `int` 與一個 `float` 相加將得到一個 `float` 。Python 把 `int` 強制轉換為 `float` 以進行加法運算;然后返回一個 `float` 類型的結果。 ### 將整數強制轉換為浮點數及反向轉換 正如剛才所看到的,一些運算符(如:加法)會根據需把整數強制轉換為浮點數。也可自行對其進行強制轉換。 ``` 2.0 2 2 -2 1.1234567890123457 <class 'int'> ``` 1. 通過調用`float()` 函數,可以顯示地將 `int` 強制轉換為 `float`。 2. 毫不出奇,也可以通過調用 `int()` 將 `float` 強制轉換為 `int` 。 3. `int()` 將進行取整,而不是四舍五入。 4. 對于負數,`int()` 函數朝著 0 的方法進行取整。它是個真正的取整(截斷)函數,而不是 floor[地板]函數。 5. 浮點數精確到小數點后 15 位。 6. 整數可以任意大。 > ?Python 2 對于`int[整型]` 和 `long[長整型]` 采用不同的數據類型。`int` 數據類型受到 `sys.maxint` 的限制,因平臺該限制也會有所不同,但通常是 `2**32-1` 。Python 3 只有一種整數類型,其行為方式很有點像 Python 2 的舊 `long[長整數]` 類型。參閱 [PEP 237](http://www.python.org/dev/peps/pep-0237) 了解更多細節。 ### 常見數值運算 對數值可進行各種類型的運算。 ``` 5.5 5 ?6 5.0 121 1 ``` 1. `/` 運算符執行浮點除法。即便分子和分母都是 `int`,它也返回一個 `float` 浮點數。 2. `//` 運算符執行古怪的整數除法。如果結果為正數,可將其視為朝向小數位取整(不是四舍五入),但是要小心這一點。 3. 當整數除以負數, `//` 運算符將結果朝著最近的整數“向上”四舍五入。從數學角度來說,由于 `?6` 比 `?5` 要小,它是“向下”四舍五入,如果期望將結果取整為 `?5`,它將會誤導你。 4. `//` 運算符并非總是返回整數結果。如果分子或者分母是 `float`,它仍將朝著最近的整數進行四舍五入,但實際返回的值將會是 `float` 類型。 5. `**` 運算符的意思是“計算冪”,`11**2` 結果為 `121` 。 6. `%` 運算符給出了進行整除之后的余數。`11` 除以 `2` 結果為 `5` 以及余數 `1`,因此此處的結果為 `1`。 > ?在 Python 2 中,運算符 `/` 通常表示整數除法,但是可以通過在代碼中加入特殊指令,使其看起來像浮點除法。在 Python 3 中,`/` 運算符總是表示浮點除法。參閱 [PEP 238](http://www.python.org/dev/peps/pep-0238/) 了解更多細節。 ### 分數 Python 并不僅僅局限于整數和浮點數類型。它可以完成你在高中階段學過、但幾乎已經全部忘光的所有古怪數學運算。 ``` >>> x Fraction(1, 3) Fraction(2, 3) Fraction(3, 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fractions.py", line 96, in __new__ raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(0, 0) ``` 1. 為啟用 fractions 模塊,必先引入 `fractions` 模塊。 2. 為定義一個分數,創建一個 `Fraction` 對象并傳入分子和分母。 3. 可對分數進行所有的常規數學計算。運算返回一個新的 `Fraction` 對象。`2 * (1/3) = (2/3)` 4. `Fraction` 對象將會自動進行約分。`(6/4) = (3/2)` 5. 在杜絕創建以零為分母的分數方面,Python 有著良好的敏感性。 ### 三角函數 還可在 Python 中進行基本的三角函數運算。 ``` >>> import math 3.1415926535897931 1.0 0.99999999999999989 ``` 1. `math` 模塊中有一個代表 π 的常量,表示圓的周長與直徑之比率(圓周率)。 2. `math` 模塊包括了所有的基本三角函數,包括:`sin()`、 `cos()`、`tan()` 及像 `asin()` 這樣的變體函數。 3. 然而要注意的是 Python 并不支持無限精度。`tan(π / 4)` 將返回 `1.0`,而不是 `0.99999999999999989`。 ### 布爾上下文環境中的數值 零值是 false[假],非零值是 true[真]。 可以在 `if` 這樣的 [布爾類型上下文環境中](#booleans) 使用數值。零值是 false[假],非零值是 true[真]。 ``` ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... yes, it's true >>> is_it_true(-1) yes, it's true >>> is_it_true(0) no, it's false yes, it's true >>> is_it_true(0.0) no, it's false >>> import fractions yes, it's true >>> is_it_true(fractions.Fraction(0, 1)) no, it's false ``` 1. 您知道可以在 Python 交互式 Shell 中定義自己的函數嗎?只需在每行的結尾按 `回車鍵` ,然后在某一空行按 `回車鍵` 結束。 2. 在布爾類型上下文環境中,非零整數為真;零為假。 3. 非零浮點數為真; `0.0` 為假。請千萬小心這一點!如果有輕微的四舍五入偏差(正如在前面小節中看到的那樣,這并非不可能的事情),那么 Python 將測試 `0.0000000000001` 而不是 0 ,并將返回一個 `True` 值。 4. 分數也可在布爾類型上下文環境中使用。無論 `n` 為何值,`Fraction(0, n)` 為假。所有其它分數為真。 ## 列表 列表是 Python 的主力數據類型。當提到 “列表 ”時,您腦海中可能會閃現“必須進一步聲明大小的數組,只能包含同一類對象“ 等想法。千萬別這么想。列表比那要酷得多。 > ? Python 中的列表類似 Perl 5 中的數組。在 Perl 5 中,存儲數組的變量總是以字符 `@` 開頭;在 Python 中,變量可隨意命名,Python 僅在內部對數據類型進行跟蹤。 > ? Python 中的列表更像 Java 中的數組(盡管可以把列表當做生命中所需要的一切來使用)。一個更好的比喻可能是 `ArrayList` 類,該類可以容納任何對象,并可在添加新元素時進行動態拓展。 ### 創建列表 列表創建非常輕松:使用中括號包裹一系列以逗號分割的值即可。 ``` >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] 'a' 'example' 'example' 'mpilgrim' ``` 1. 首先,創建一個包含 5 個元素的列表。要注意的是它們保持了最初的順序。這并不是偶然的。列表是元素的有序集合。 2. 列表可當做以零為基點的數組使用。非空列表的首個元素始終是 `a_list[0]` 。 3. 該 5 元素列表的最后一個元素是 `a_list[4]`,因為列表(索引)總是以零為基點的。 4. 使用負索引值可從列表的尾部向前計數訪問元素。任何非空列表的最后一個元素總是 `a_list[-1]` 。 5. 如果負數令你混淆,可將其視為如下方式: `a_list[-`n`] == a_list[len(a_list) - `n`]` 。因此在此列表中, `a_list[-3] == a_list[5 - 3] == a_list[2]`。 ### 列表切片 a_list[0] 是列表的第一個元素。 定義列表后,可從其中獲取任何部分作為新列表。該技術稱為對列表進行 _切片_ 。 ``` >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] ['b', 'mpilgrim'] ['b', 'mpilgrim', 'z'] ['a', 'b', 'mpilgrim'] ['a', 'b', 'mpilgrim'] ['z', 'example'] ['a', 'b', 'mpilgrim', 'z', 'example'] ``` 1. 通過指定兩個索引值,可以從列表中獲取稱作“切片”的某個部分。返回值是一個新列表,它包含列表(??切片)中所有元素,按順序從第一個切片索引開始(本例中為 `a_list[1]`),截止但不包含第二個切片索引(本例中的 `a_list[3]`)。 2. 如果切片索引之一或兩者均為負數,切片操作仍可進行。如果有幫助的話,您可以這么思考:自左向右讀取列表,第一個切片索引指明了想要的第一個元素,第二個切片索引指明了第一個不想要的元素。返回值是兩者之間的任何值。 between. 3. 列表是以零為起點的,因此 `a_list[0:3]` 返回列表的頭三個元素,從 `a_list[0]` 開始,截止到但不包括 `a_list[3]` 。 4. 如果左切片索引為零,可以將其留空而將零隱去。因此 `a_list[:3]` 與 `a_list[0:3]` 是完全相同的,因為起點 0 被隱去了。 5. 同樣,如果右切片索引為列表的長度,也可以將其留空。因此 `a_list[3:]` 與 `a_list[3:5]` 是完全相同的,因為該列表有五個元素。此處有個好玩的對稱現象。在這個五元素列表中, `a_list[:3]` 返回頭三個元素,而 `a_list[3:]` 返回最后兩個元素。事實上,無論列表的長度是多少, `a_list[:`n`]` 將返回頭 `n` 個元素,而 `a_list[`n`:]` 返回其余部分。 6. 如果兩個切片索引都留空,那么將包括列表所有的元素。但該返回值與最初的 `a_list` 變量并不一樣。它是一個新列表,只不過恰好擁有完全相同的元素而已。`a_list[:]` 是對列表進行復制的一條捷徑。 ### 向列表中新增項 有四種方法可用于向列表中增加元素。 ``` >>> a_list = ['a'] ['a', 2.0, 3] >>> a_list ['a', 2.0, 3, True] >>> a_list ['a', 2.0, 3, True, 'four', 'Ω'] >>> a_list ['Ω', 'a', 2.0, 3, True, 'four', 'Ω'] ``` 1. `+` 運算符連接列表以創建一個新列表。列表可包含任何數量的元素;沒有大小限制(除了可用內存的限制)。然而,如果內存是個問題,那就必須知道在進行連接操作時,將在內存中創建第二個列表。在該情況下,新列表將會立即被賦值給已有變量 `a_list` 。因此,實際上該行代碼包含兩個步驟?—?連接然后賦值?—?當處理大型列表時,該操作可能(暫時)消耗大量內存。 2. 列表可包含任何數據類型的元素,單個列表中的元素無須全為同一類型。下面的列表中包含一個字符串、一個浮點數和一個整數。 3. `append()` 方法向列表的尾部添加一個新的元素。(現在列表中有 _四種_ 不同數據類型!) 4. 列表是以類的形式實現的。“創建”列表實際上是將一個類實例化。因此,列表有多種方法可以操作。`extend()` 方法只接受一個列表作為參數,并將該參數的每個元素都添加到原有的列表中。 5. `insert()` 方法將單個元素插入到列表中。第一個參數是列表中將被頂離原位的第一個元素的位置索引。列表中的元素并不一定要是唯一的;比如說:現有兩個各自獨立的元素,其值均為 `'Ω'`:,第一個元素 `a_list[0]` 以及最后一個元素 `a_list[6]` 。 > ?``a_list`.insert(0, `value`)` 就像是 Perl 中的 `unshift()` 函數。它將一個元素添加到列表的頭部,所有其它的元素都被頂理原先的位置以騰出空間。 讓我們進一步看看 `append()` 和 `extend()` 的區別。 ``` >>> a_list = ['a', 'b', 'c'] >>> a_list ['a', 'b', 'c', 'd', 'e', 'f'] 6 >>> a_list[-1] 'f' >>> a_list ['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']] 7 >>> a_list[-1] ['g', 'h', 'i'] ``` 1. `extend()` 方法只接受一個參數,而該參數總是一個列表,并將列表 `a_list` 中所有的元素都添加到該列表中。 2. 如果開始有個 3 元素列表,然后將它與另一個 3 元素列表進行 extend 操作,結果是將獲得一個 6 元素列表。 3. 另一方面, `append()` 方法只接受一個參數,但可以是任何數據類型。在此,對一個 3 元素列表調用 `append()` 方法。 4. 如果開始的時候有個 6 元素列表,然后將一個列表 append[添加]上去,結果就會……得到一個 7 元素列表。為什么是 7 個?因為最后一個元素(剛剛 append[添加] 的元素) _本身是個列表_ 。列表可包含任何類型的數據,包括其它列表。這可能是你所需要的結果,也許不是。但如果這就是你想要的,那這就是你所得到的。 ### 在列表中檢索值 ``` >>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] 2 True >>> 'c' in a_list False 3 2 Traceback (innermost last): File "<interactive input>", line 1, in ?ValueError: list.index(x): x not in list ``` 1. 如你所期望, `count()` 方法返回了列表中某個特定值出現的次數。 2. 如果你想知道的是某個值是否出現在列表中, `in` 運算符將會比使用 `count()` 方法要略快一些。`in` 運算符總是返回 `True` 或 `False`;它不會告訴你該值出現在什么位置。 3. 如果想知道某個值在列表中的精確位置,可調用 `index()` 方法。盡管可以通過第二個參數(以 0 為基點的)索引值來指定起點,通過第三個參數(以 0 基點的)索引來指定搜索終點,但缺省情況下它將搜索整個列表, 4. `index()` 方法將查找某值在列表中的_第一次_出現。在該情況下,`'new'` 在列表中出現了兩次,分別為 `a_list[2]` 和 `a_list[4]`,但 `index()` 方法將只返回第一次出現的位置索引值。 5. 可能 _出乎_ 您的預期,如果在列表中沒有找到該值,`index()` 方法將會引發一個例外。 等等,什么?是這樣的:如果沒有在列表中找到該值, `index()` 方法將會引發一個例外。這是 Python 語言最顯著不同之處,其它多數語言將會返回一些無效的索引值(像是 `-1`)。當然,一開始這一點看起來比較討厭,但我想您會逐漸欣賞它。這意味著您的程序將會在問題的源頭處崩潰,而不是之后奇怪地、默默地崩潰。請記住, [`-1` 是合法的列表索引值](#creatinglists)。如果 `index()` 方法返回 `-1`,可能會導致調整過程變得不那么有趣! ### 從列表中刪除元素 列表永遠不會有縫隙。 列表可以自動拓展或者收縮。您已經看到了拓展部分。也有幾種方法可從列表中刪除元素。 ``` >>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'b' >>> a_list ['a', 'new', 'mpilgrim', 'new'] 'new' ``` 1. 可使用 `del` 語句從列表中刪除某個特定元素。 2. 刪除索引 `1` 之后再訪問索引 `1` 將 _不會_ 導致錯誤。被刪除元素之后的所有元素將移動它們的位置以“填補”被刪除元素所產生的“縫隙”。 不知道位置索引?這不成問題,您可以通過值而不是索引刪除元素。 ``` >>> a_list ['a', 'mpilgrim', 'new'] >>> a_list ['a', 'mpilgrim'] >>> a_list.remove('new') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: list.remove(x): x not in list ``` 1. 還可以通過 `remove()` 方法從列表中刪除某個元素。`remove()` 方法接受一個 _value_ 參數,并刪除列表中該值的第一次出現。同樣,被刪除元素之后的所有元素將會將索引位置下移,以“填補縫隙”。列表永遠不會有“縫隙”。 2. 您可以盡情地調用 `remove()` 方法,但如果試圖刪除列表中不存在的元素,它將引發一個例外。 ### Removing Items From A List: Bonus Round 另一有趣的列表方法是 `pop()` 。`pop()` 方法是[從列表刪除元素](#removingfromlists)的另一方法,但有點變化。 ``` >>> a_list = ['a', 'b', 'new', 'mpilgrim'] 'mpilgrim' >>> a_list ['a', 'b', 'new'] 'b' >>> a_list ['a', 'new'] >>> a_list.pop() 'new' >>> a_list.pop() 'a' Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: pop from empty list ``` 1. 如果不帶參數調用, `pop()` 列表方法將刪除列表中最后的元素,_并返回所刪除的值_。 2. 可以從列表中 pop[彈出]任何元素。只需傳給 `pop()` 方法一個位置索引值。它將刪除該元素,將其后所有元素移位以“填補縫隙”,然后返回它刪除的值。 3. 對空列表調用 `pop()` 將會引發一個例外。 > ?不帶參數調用的 `pop()` 列表方法就像 Perl 中的 `pop()` 函數。它從列表中刪除最后一個元素并返回所刪除元素的值。Perl 還有另一個函數 `shift()`,可用于刪除第一個元素并返回其值;在 Python 中,該函數相當于 ``a_list`.pop(0)` 。 ### 布爾上下文環境中的列表 空列表為假;其它所有列表為真。 可以在 `if` 這樣的 [布爾類型上下文環境中](#booleans) 使用列表。 ``` >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... no, it's false yes, it's true yes, it's true ``` 1. 在布爾類型上下文環境中,空列表為假值。 2. 任何至少包含一個上元素的列表為真值。 3. 任何至少包含一個上元素的列表為真值。元素的值無關緊要。 ## 元組 元素 是不可變的列表。一旦創建之后,用任何方法都不可以修改元素。 ``` >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') 'a' 'example' ('b', 'mpilgrim') ``` 1. 元組的定義方式和列表相同,除了整個元素的集合都用圓括號,而不是方括號閉合。 2. 和列表一樣,元組的元素都有確定的順序。元組的索引也是以零為基點的,和列表一樣,因此非空元組的第一個元素總是 `a_tuple[0]` 。 3. 負的索引從元組的尾部開始計數,這和列表也是一樣的。 4. 和列表一樣,元組也可以進行切片操作。對列表切片可以得到新的列表;對元組切片可以得到新的元組。 元組和列表的主要區別是元組不能進行修改。用技術術語來說,元組是 不可變更 的。從實踐的角度來說,沒有可用于修改元組的方法。列表有像 `append()`、 `extend()`、 `insert()`、`remove()` 和 `pop()` 這樣的方法。這些方法,元組都沒有。可以對元組進行切片操作(因為該方法創建一個新的元組),可以檢查元組是否包含了特定的值(因為該操作不修改元組),還可以……就那么多了。 ``` # continued from the previous example >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'append' Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'remove' 4 True ``` 1. 無法向元組添加元素。元組沒有 `append()` 或 `extend()` 方法。 2. 不能從元組中刪除元素。元組沒有 `remove()` 或 `pop()` 方法。 3. _可以_ 在元組中查找元素,由于該操作不改變元組。 4. 還可以使用 `in` 運算符檢查某元素是否存在于元組中。 那么元組有什么好處呢? * 元組的速度比列表更快。如果定義了一系列常量值,而所需做的僅是對它進行遍歷,那么請使用元組替代列表。 * 對不需要改變的數據進行“寫保護”將使得代碼更加安全。使用元組替代列表就像是有一條隱含的 `assert` 語句顯示該數據是常量,特別的想法(及特別的功能)必須重寫。(??) * 一些元組可用作字典鍵(特別是包含字符串、數值和其它元組這樣的_不可變_數據的元組)。列表永遠不能當做字典鍵使用,因為列表不是不可變的。 > ?元組可轉換成列表,反之亦然。內建的 `tuple()` 函數接受一個列表參數,并返回一個包含同樣元素的元組,而 `list()` 函數接受一個元組參數并返回一個列表。從效果上看, `tuple()` 凍結列表,而 `list()` 融化元組。 ### 布爾上下文環境中的元組 可以在 `if` 這樣的 [布爾類型上下文環境中](#booleans) 使用元組。 ``` >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... no, it's false yes, it's true yes, it's true <class 'bool'> >>> type((False,)) <class 'tuple'> ``` 1. 在布爾類型上下文環境中,空元組為假值。 2. 任何至少包含一個上元素的元組為真值。 3. 任何至少包含一個上元素的元組為真值。元素的值無關緊要。不過此處的逗號起什么作用呢? 4. 為創建單元素元組,需要在值之后加上一個逗號。沒有逗號,Python 會假定這只是一對額外的圓括號,雖然沒有害處,但并不創建元組。 ### 同時賦多個值 以下是一種很酷的編程捷徑:在 Python 中,可使用元組來一次賦多值。 ``` >>> v = ('a', 2, True) >>> x 'a' >>> y 2 >>> z True ``` 1. `v` 是一個三元素的元組,而 `(x, y, z)` 是包含三個變量的元組。將其中一個賦值給另一個將會把 `v` 中的每個值按順序賦值給每一個變量。 該特性有多種用途。假設需要將某個名稱指定某個特定范圍的值。可以使用內建的 `range()` 函數進行多變量賦值以快速地進行連續變量賦值。 ``` 0 >>> TUESDAY 1 >>> SUNDAY 6 ``` 1. 內建的 `range()` 函數構造了一個整數序列。(從技術上來說, `range()` 函數返回的既不是列表也不是元組,而是一個 [迭代器](iterators.html),但稍后您將學到它們的區別。) `MONDAY`、 `TUESDAY`、 `WEDNESDAY`、 `THURSDAY`、 `FRIDAY`、 `SATURDAY` 和 `SUNDAY` 是您所定義的變量。(本例來自于 `calendar` 模塊,該短小而有趣的模塊打印日歷,有點像 UNIX 程序 `cal` 。該 `calendar` 模塊為星期數定義了整數常量。 2. 現在,每個變量都有其值了: `MONDAY` 為 0, `TUESDAY` 為 `1`,如此類推。 還可以使用多變量賦值創建返回多值的函數,只需返回一個包含所有值的元組。調用者可將返回值視為一個簡單的元組,或將其賦值給不同的變量。許多標準 Python 類庫這么干,包括在[下一章](comprehensions.html#os)將學到的 `os` 模塊。 ## 集合 集合set 是裝有獨特值的無序“袋子”。一個簡單的集合可以包含任何數據類型的值。如果有兩個集合,則可以執行像聯合、交集以及集合求差等標準集合運算。 ### 創建集合 重中之重。創建集合非常簡單。 ``` >>> a_set {1} <class 'set'> >>> a_set {1, 2} ``` 1. 要創建只包含一個值的集合,僅需將該值放置于花括號之間。(`{}`)。 2. 實際上,集合以 [類](iterators.html#defining-classes) 的形式實現,但目前還無須考慮這一點。 3. 要創建多值集合,請將值用逗號分開,并用花括號將所有值包裹起來。 還可以 [列表](#lists) 為基礎創建集合。 ``` >>> a_list = ['a', 'b', 'mpilgrim', True, False, 42] {'a', False, 'b', True, 'mpilgrim', 42} ['a', 'b', 'mpilgrim', True, False, 42] ``` 1. 要從列表創建集合,可使用 `set()` 函數。(懂得如何實現集合的學究可能指出這實際上并不是調用某個函數,而是對某個類進行實例化。我_保證_在本書稍后的地方將會學到其中的區別。目前而言,僅需知道 `set()` 行為與函數類似,以及它返回一個集合。) 2. 正如我之前提到的,簡單的集合可以包括任何數據類型的值。而且,如我之前所提到的,集合是 _無序的_。該集合并不記得用于創建它的列表中元素的最初順序。如果向集合中添加元素,它也不會記得添加的順序。 3. 初始的列表并不會發生變化。 還沒有任何值?沒有問題。可以創建一個空的集合。 ``` set() <class 'set'> 0 >>> type(not_sure) <class 'dict'> ``` 1. 要創建空集合,可不帶參數調用 `set()` 。 2. 打印出來的空集合表現形式看起來有點兒怪。也許,您期望看到一個 `{}` 吧 ?該符號表示一個空的字典,而不是一個空的集合。本章稍后您將學到關于字典的內容。 3. 盡管打印出的形式奇怪,這 _確實是_ 一個集合…… 4. …… 同時該集合沒有任何成員。 5. 由于從 Python 2 沿襲而來歷史的古怪規定,不能使用兩個花括號來創建空集合。該操作實際創建一個空字典,而不是一個空集合。 ### 修改集合 有兩種方法可向現有集合中添加值: `add()` 方法和 `update()` 方法。 ``` >>> a_set = {1, 2} >>> a_set {1, 2, 4} 3 >>> a_set {1, 2, 4} 3 ``` 1. `add()` 方法接受單個可以是任何數據類型的參數,并將該值添加到集合之中。 2. 該集合現在有三個成員了。 3. 集合是裝 _唯一值_ 的袋子。如果試圖添加一個集合中已有的值,將不會發生任何事情。將不會引發一個錯誤;只是一條空操作。 4. 該集合 _仍然_ 只有三個成員。 ``` >>> a_set = {1, 2, 3} >>> a_set {1, 2, 3} {1, 2, 3, 4, 6} >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 13} >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30} ``` 1. `update()` 方法僅接受一個集合作為參數,并將其所有成員添加到初始列表中。其行為方式就像是對參數集合中的每個成員調用 `add()` 方法。 2. 由于集合不能包含重復的值,因此重復的值將會被忽略。 3. 實際上,可以帶任何數量的參數調用 `update()` 方法。如果調用時傳遞了兩個集合, `update()` 將會被每個集合中的每個成員添加到初始的集合當中(丟棄重復值)。 4. `update()` 方法還可接受一些其它數據類型的對象作為參數,包括列表。如果調用時傳入列表,`update()` 將會把列表中所有的元素添加到初始集合中。 ### 從集合中刪除元素 有三種方法可以用來從集合中刪除某個值。前兩種,`discard()` 和 `remove()` 有細微的差異。 ``` >>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} >>> a_set {1, 3, 36, 6, 10, 45, 15, 21, 28} >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set {1, 3, 36, 6, 45, 15, 28} Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 21 ``` 1. `discard()` 接受一個單值作為參數,并從集合中刪除該值。 2. 如果針對一個集合中不存在的值調用 `discard()` 方法,它不進行任何操作。不產生錯誤;只是一條空指令。 3. `remove()` 方法也接受一個單值作為參數,也從集合中將其刪除。 4. 區別在這里:如果該值不在集合中,`remove()` 方法引發一個 `KeyError` 例外。 就像列表,集合也有個 `pop()` 方法。 ``` >>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} 1 >>> a_set.pop() 3 >>> a_set.pop() 36 >>> a_set {6, 10, 45, 15, 21, 28} >>> a_set set() Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'pop from an empty set' ``` 1. `pop()` 方法從集合中刪除某個值,并返回該值。然而,由于集合是無序的,并沒有“最后一個”值的概念,因此無法控制刪除的是哪一個值。它基本上是隨機的。 2. `clear()` 方法刪除集合中 _所有_ 的值,留下一個空集合。它等價于 `a_set = set()`,該語句創建一個新的空集合,并用之覆蓋 `a_set` 變量的之前的值。 3. 試圖從空集合中彈出某值將會引發 `KeyError` 例外。 ### 常見集合操作 Python 的 `集合` 類型支持幾種常見的運算。 ``` >>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195} True >>> 31 in a_set False >>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21} {1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127} {9, 2, 12, 5, 21} {195, 4, 76, 51, 30, 127} {1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51} ``` 1. 要檢測某值是否是集合的成員,可使用 `in` 運算符。其工作原理和列表的一樣。 2. `union()` 方法返回一個新集合,其中裝著 _在兩個_ 集合中出現的元素。 3. `intersection()` 方法返回一個新集合,其中裝著 _同時_ 在兩個集合中出現的所有元素。 4. `difference()` 方法返回的新集合中,裝著所有在 `a_set` 出現但未在 `b_set` 中的元素。 5. `symmetric_difference()` 方法返回一個新集合,其中裝著所有 _只在其中一個_ 集合中出現的元素。 這三種方法是對稱的。 ``` # continued from the previous example {3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127} True True True False ``` 1. `a_set` 與 `b_set` 的對稱差分 _看起來_ 和`b_set` 與 `a_set` 的對稱差分不同,但請記住:集合是無序的。任何兩個包含所有同樣值(無一遺漏)的集合可認為是相等的。 2. 而這正是這里發生的事情。不要被 Python Shell 對這些集合的輸出形式所愚弄了。它們包含相同的值,因此是相等的。 3. 對兩個集合的 Union[并集]操作也是對稱的。 4. 對兩個集合的 Intersection[交集]操作也是對稱的。 5. 對兩個集合的 Difference[求差]操作不是對稱的。這是有意義的;它類似于從一個數中減去另一個數。操作數的順序會導致結果不同。 最后,有幾個您可能會問到的問題。 ``` >>> a_set = {1, 2, 3} >>> b_set = {1, 2, 3, 4} True True >>> a_set.issubset(b_set) False >>> b_set.issuperset(a_set) False ``` 1. `a_set` 是 `b_set`?的 子集 —?所有 `a_set` 的成員均為 `b_set` 的成員。 2. 同樣的問題反過來說, `b_set` 是 `a_set` 的 超集,因為 `a_set` 的所有成員均為 `b_set` 的成員。 3. 一旦向 `a_set` 添加一個未在 `b_set` 中出現的值,兩項測試均返回 `False` 。 ### 布爾上下文環境中的集合 可在 `if` 這樣的 [布爾類型上下文環境中](#booleans) 使用集合。 ``` >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... no, it's false yes, it's true yes, it's true ``` 1. 在布爾類型上下文環境中,空集合為假值。 2. 任何至少包含一個上元素的集合為真值。 3. 任何至少包含一個上元素的集合為真值。元素的值無關緊要。 ## 字典 字典 是鍵值對的無序集合。向字典添加一個鍵的同時,必須為該鍵增添一個值。(之后可隨時修改該值。) Python 的字典為通過鍵獲取值進行了優化,而不是反過來。 > ?Python 中的字典與 Perl 5 中的 hash [散列]類似。在 Perl 5 中,散列存儲的變量總是以一個 `%` 符開頭。在 Python 中,變量可以隨意命名,而 Python 內部跟蹤其數據類型。 ### 創建字典 創建字典非常簡單。其語法與 [集合](#sets) 的類似,但應當指定鍵值對而不是值。有了字典后,可以通過鍵來查找值。 ``` >>> a_dict {'server': 'db.diveintopython3.org', 'database': 'mysql'} 'db.diveintopython3.org' 'mysql' Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'db.diveintopython3.org' ``` 1. 首先,通過將兩個字典項指定給 `a_dict` 變量創建了一個新字典。每個字典項都是一組鍵值對,整個字典項集合都被大括號包裹在內。 2. `'server'` 為鍵,通過 `a_dict['server']` 引用的關聯值為 `'db.diveintopython3.org'` 。 3. `'database'` 為鍵,通過 `a_dict['database']` 引用的關聯值為 `'mysql'` 。 4. 可以通過鍵獲取值,但不能通過值獲取鍵。因此 `a_dict['server']` 為 `'db.diveintopython3.org'`,而 `a_dict['db.diveintopython3.org']` 會引發例外,因為 `'db.diveintopython3.org'` 并不是鍵。 ### 修改字典 字典沒有預定義的大小限制。可以隨時向字典中添加新的鍵值對,或者修改現有鍵所關聯的值。繼續前面的例子: ``` >>> a_dict {'server': 'db.diveintopython3.org', 'database': 'mysql'} >>> a_dict {'server': 'db.diveintopython3.org', 'database': 'blog'} {'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'} >>> a_dict {'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'} >>> a_dict {'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'} ``` 1. 在字典中不允許有重復的鍵。對現有的鍵賦值將會覆蓋舊值。 2. 可隨時添加新的鍵值對。該語法與修改現有值相同。 3. 新字典項(鍵為 `'user'`,值為 `'mark'`)出現在中間。事實上,在第一個例子中字典項按順序出現是個巧合;現在它們不按順序出現同樣也是個巧合。 4. 對既有字典鍵進行賦值只會用新值替代舊值。 5. 該操作會將 `user` 鍵的值改回 "mark" 嗎?不會!仔細看看該鍵——有個大寫的 `U` 出現在 `"User"` 中。字典鍵是區分大小寫的,因此該語句創建了一組新的鍵值對,而不是覆蓋既有的字典項。對你來說它們可能是一樣的,但對于 Python 而言它們是完全不同的。 ### 混合值字典 字典并非只能用于字符串。字典的值可以是任何數據類型,包括整數、布爾值、任何對象,甚至是其它的字典。而且就算在同一字典中,所有的值也無須是同一類型,您可根據需要混合匹配。字典的鍵要嚴格得多,可以是字符串、整數和其它一些類型。在同一字典中也可混合、匹配使用不同數據類型的鍵。 實際上,您已經在 [your first Python program](your-first-python-program.html#divingin) 見過一個將非字符串用作鍵的字典了。 ``` SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']} ``` 讓我們在交互式 shell 中剖析一下: ``` >>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], ... 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']} 2 True ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] 'TB' ``` 1. 類似 [列表](#lists) 和 [集合](#sets) ,`len()` 函數將返回字典中鍵的數量。 2. 而且像列表和集合一樣,可使用 `in` 運算符以測試某個特定的鍵是否在字典中。 3. `1000` _是_ 字典 `SUFFIXES` 的一個鍵;其值為一個 8 元素列表(確切地說,是 8 個字符串)。 4. 同樣, `1024` 是字典 `SUFFIXES` 的鍵;其值也是一個 8 元素列表。 5. 由于 `SUFFIXES[1000]` 是列表,可以通過它們的 0 基點索引來獲取列表中的單個元素。 ### 布爾上下文環境中的字典 空字典為假值;所有其它字典為真值。 可以在 `if` 這樣的 [布爾類型上下文環境中](#booleans) 使用字典。 ``` >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... no, it's false yes, it's true ``` 1. 在布爾類型上下文環境中,空字典為假值。 2. 至少包含一個鍵值對的字典為真值。 ## `None` `None` 是 Python 的一個特殊常量。它是一個 空 值。`None` 與 `False` 不同。`None` 不是 0 。`None` 不是空字符串。將 `None` 與任何非 `None` 的東西進行比較將總是返回 `False` 。 `None` 是唯一的空值。它有著自己的數據類型(`NoneType`)。可將 `None` 賦值給任何變量,但不能創建其它 `NoneType` 對象。所有值為 `None` 變量是相等的。 ``` >>> type(None) <class 'NoneType'> >>> None == False False >>> None == 0 False >>> None == '' False >>> None == None True >>> x = None >>> x == None True >>> y = None >>> x == y True ``` ### 布爾上下文環境中的 `None` 在 [布爾類型上下文環境中](#booleans), `None` 為假值,而 `not None` 為真值。 ``` >>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(None) no, it's false >>> is_it_true(not None) yes, it's true ``` ## 深入閱讀 * [布爾運算](http://docs.python.org/3.1/library/stdtypes.html#boolean-operations-and-or-not) * [數值類型](http://docs.python.org/3.1/library/stdtypes.html#numeric-types-int-float-long-complex) * [序列類型](http://docs.python.org/3.1/library/stdtypes.html#sequence-types-str-unicode-list-tuple-buffer-xrange) * [集合類型](http://docs.python.org/3.1/library/stdtypes.html#set-types-set-frozenset) * [映射類型](http://docs.python.org/3.1/library/stdtypes.html#mapping-types-dict) * [`fractions[分數]` 模塊](http://docs.python.org/3.1/library/fractions.html) * [`math[數學]` 模塊](http://docs.python.org/3.1/library/math.html) * [PEP 237: 統一長整數和整數](http://www.python.org/dev/peps/pep-0237/) * [PEP 238: 修改除法運算符](http://www.python.org/dev/peps/pep-0238/) 您在這里: [主頁](index.html) ? [深入Python 3](table-of-contents.html#comprehensions) ?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看