天天看點

第二章 文法及代碼約定

 第二章 文法及代碼約定

本章講述了Python程式的文法和代碼約定。 本章的主題有行結構,語句分組,保留字,字元串,運算符,token等等,另外對如何使用 Unicode 字元串也做了詳細的描述。

1.1. 行結構/縮進

程式中的每個語句都以換行符結束。特别長的語句可以使用續行符(/)來分成幾個短小的行,如下例:

import math
a = math,cos(3*(x-n)) + /
    math,sin(3*(y-n))
      

當你定義一個三引号字元串、清單、tuple 或者字典的時候不需要續行符來分割語句。及就是說,在程式中,凡是圓括号(,,,)、方括号[,,,]、花括号{,,,}及三引号字元串内的部分均不需要使用續行符。

縮進被用來訓示不同的代碼塊,比如函數的主體代碼塊,條件執行代碼塊,循環體代碼塊及類定義代碼塊。縮進的空格(制表符)數目可以是任意的,但是在整個塊中的縮進必須一緻:

<script type="text/javascript"> function isnumbered(obj) { return obj.childNodes.length && obj.firstChild.childNodes.length && obj.firstChild.firstChild.className == 'LineNumber'; } function nformat(num,chrs,add) { var nlen = Math.max(0,chrs-(''+num).length), res = ''; while (nlen>0) { res += ' '; nlen-- } return res+num+add; } function addnumber(did, nstart, nstep) { var c = document.getElementById(did), l = c.firstChild, n = 1; if (!isnumbered(c)) if (typeof nstart == 'undefined') nstart = 1; if (typeof nstep == 'undefined') nstep = 1; n = nstart; while (l != null) { if (l.tagName == 'SPAN') { var s = document.createElement('SPAN'); s.className = 'LineNumber' s.appendChild(document.createTextNode(nformat(n,4,' '))); n += nstep; if (l.childNodes.length) l.insertBefore(s, l.firstChild) else l.appendChild(s) } l = l.nextSibling; } return false; } function remnumber(did) { var c = document.getElementById(did), l = c.firstChild; if (isnumbered(c)) while (l != null) { if (l.tagName == 'SPAN' && l.firstChild.className == 'LineNumber') l.removeChild(l.firstChild); l = l.nextSibling; } return false; } function togglenumber(did, nstart, nstep) { var c = document.getElementById(did); if (isnumbered(c)) { remnumber(did); } else { addnumber(did,nstart,nstep); } return false; } </script><script type="text/javascript"> document.write(' Toggle line numbers '); </script> Toggle line numbers

1 if a:
   2    statement1     # 縮進一緻,正确!
   3    statement2
   4 else:
   5    statement3
   6      statement4   #縮進不一緻,錯誤!
      
如果塊中隻有很少的語句,那麼你也可以把它們放置在同一行:

if a:  statement1
else:  statement2

要表示一個空的塊或是空的主體,使用 pass語句:

if a:
   pass
else:
   statements
      

盡管允許用制表符訓示縮進,我還是要說這是一個不好的習慣。 堅決不要混合使用制表符和空格來縮進,這會給你帶來意想不到的麻煩。建議你在每個縮進層次中使用單個制表符或兩個或四個空格。運作 Python的時候使用 -t 參數,如果python 發現存在制表符和空格混用,它就顯示警告資訊,若使用 -tt 參數 python 則會在遇到混用情況時引發TabError異常。

分号(;)可以把多個語句放在同一行中,隻有一個語句的行也可以用分号來結束。

#訓示這是一個延長至行末的注釋,但是包在字元串内的#沒有這個功能。

最後要說明的,解釋器會忽略所有的空白行(非互動模式下)。

1.2. 辨別符及保留字

辨別符是用于識别變量、函數、類、子產品以及其他對象的名字,辨別符可以包含字母、數字及下劃線(_),但是必須以一個非數字字元開始。字母僅僅包括ISO-Latin字元集中的A–Z和a–z。辨別符是大小寫敏感的,是以 FOO和foo是兩個不同的對象。特殊符号,如$、%、@等,不能用在辨別符中。另外,如 if,else,for 等單詞是保留字,也不能将其用作辨別符。下面的表列出了所有的保留字元:

and             elif                    global                  or
assert          else                    if                      pass
break           except                  import                  print
class           exec                    in                      raise
continue        finally                 is                      return
def             for                     lambda                  try
del             from                    not                     while
      

以下劃線開始或者結束的辨別符通常有特殊的意義。例如以一個下劃線開始的辨別符(如 _foo)不能用from module import *語句導入。前後均有兩個下劃線的辨別符,如__init__,被特殊方法保留。前邊有兩個下劃線的辨別符,如__bar,被用來實作類私有屬性,這個将在第七章--類與面向對象程式設計中講到。通常情況下,應該避免使用相似的辨別符。

1.3. 數字/文字

Python中有四種内建的數值類型:整數、長整數、浮點數和複數。

象1234這樣的數被解析為一個十進制的整數。要指定一個八進制或者十六進制的整數,在一個合法的八進制數前加上 0 或者在一個合法的16進制數前加上 0x 就可以了。(如 0644 和 0x100fea8)。 在一個整數後面加上字母 l 或 L系統就認為這是一個長整數(如 1234567890L)。與受機器字長限制整數類型不同,長整數可以是任何長度(隻受記憶體大小限制)。象123.34和1.2334e+02這樣的數被解析為浮點數。一個整數或者浮點數加上字尾 J 或者 j 就構成了一個複數的虛部,你可以用一個實數加上一個虛部建立一個複數,比如 1.2 + 12.34J。

Python目前支援兩種類型的字元串:

8位字元資料 (ASCII)

16位寬字元資料 (Unicode)

最常用的是ASCII字元串,因為這個字元集剛好隻用一個位元組就可以字元集中的任意一個字元。通常情況下,ASCII串用單引号('),雙引号("),或者三引号(''' 或 """)來定義。字元串前後的引号類型必須一緻。反斜杠(/)用來轉義特殊字元,比如換行符、反斜杠本身、引号以及其他非列印字元。Table 2.1中列出了公認的特殊字元的表示方法,無法識别的轉義字元串将被原樣保留(包括前邊的反斜杠)。此外,字元串可以包含嵌入的空位元組和二進制資料。三引号字元串中可以包含不必轉義的換行符和引号。

Table 2.1 Standard Character Escape Codes

标準特殊字元
字元 描述
/ 續行符
// 反斜杠
/' 單引号
/" 雙引号
/a Bell(音箱發出吡的一聲)
/b 倒退符
/e Escape
/0 Null(空值)
/n 換行符,等價于/x0a和/cJ
/v 垂直制表符,等價于/x0b和/cK
/t 水準制表符,等價于/x09和/cI
/r 回車符,等價于/x0d和/cM
/f 換頁符,等價于/x0c和/cL
/OOO 八進制值(000-377)
/xhh 十六進制值(x00-xff)
/un Unicode字元值,n是四個十六進制數字表示的Unicode字元
Unicode 字元串用來表示多位元組國際字元集,它包括65,536個字元。Unicode字元使用u或者U字首來定義,例如`a = u"hello"`。在Unicode字元集中,每一個字元用一個16位整數來表示。Unicode字元使用 U+XXXX 這種形式來表示,XXXX是一個由 4 個十六進制數字組成的16進制數。(注意: 這種記法隻是一個表示Unicode字元的習慣,并不是Python的文法)。例如U+0068是Unicode字元字母h(在Latin-1字元集中,你可以發現Unicode字元集的前256個字元與Lation-1的對應字元編碼完全相同)。當Unicode字元串被指派時普通字元和特殊字元都直接轉換成Unicode字元序數(在[U+0000, U+00FF]中)。例如,字元串"hello/n"映射為ASCII時是:0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a,當使用u"hello/n"轉換為Unicode字元串時是:U+0068, U+0065, U+006C, U+006C, U+006F, U+000A.任意Unicode字元都可以使用/uXXXX來定義,/uXXXX必須位于一個Unicode字元串中,例如:

s = u"/u0068/u0065/u006c/u006c/u006f/u000a"

在Python 的較老版本中,/xXXXX位元組序列被用來定義Unicode字元(這與系統識别Unicode字元方式有關)。雖然現在仍然允許這樣做,我仍然建議你最好采用新的表示方法。(因為舊的表示方法随時可能廢止。)另外,八進制代碼/OOO也可以用來定義在[U+0000, U+01FF]中的Unicode字元。

Unicode字元不能通過使用 UTF-8或者UTF-16編碼中的原始位元組序列來定義。例如,UTF-8編碼的字元串 u'M/303/274ller' 建立的七個字元,用Unicode表示為+004D, U+00C3, U+00BC, U+006C, U+006C, U+0065, U+0072,這并不是你想要的結果。這是因為在UTF-8中,多位元組序列/303/274用來代表U+00FC,而不是U+00C3, U+00BC。更多關于Unicode編碼細節你可以閱讀第三章--"類型和對象",第四章--"運算符和表達式",第九章--"輸入和輸出".

你可以給一個字元串加上字首r或者R,例如 `r'/n/"'`,這些字元串被稱為原始字元串,因為裡邊幾乎所有的特殊字元都會原封不動地留下。不過原始字元串并不能以一個單獨的反斜杠結尾(例如 r"/")。如果原始字元串使用ur或者UR字首來定義的話,/uXXXX仍然會被解析為Unicode字元。如果你不想這樣,你可以在它前邊再加一個反斜杠,例如ur"//u1234",它定義了一個含有7個字元的字元串。需要注意的是,定義原始Unicode字元串時,r必須在u之後。

鄰近的字元串(被空格或者續行符分割),例如 "hello" 'world' 會被Python自動連結為一個字元串 "helloworld"。無論是普通字元串,Unicode字元串,還是自然字元串,都會自動連結。當然,隻要這些字元串中有一個是Unicode字元串,那最終連結的結果也将是一個Unicode字元串。比如 "s1" u"s2" 就會産生 u"s1s2"。這個過程的細節你可以閱讀第四章和附錄A(the Python library).

如果Python在 -U 指令行參數下運作,所有的字元都會被解析為Unicode。

方括号[...]定義一個清單,圓括号(...)定義一個元組,花括号{...}定義一個字典:

 a = [ 1, 3.4, 'hello' ]           # A list
 b = ( 10, 20, 30 )                # A tuple
 c = { 'a': 3, 'b':42 }            # A dictionary 
      

1.4. 運算符、分隔符及特殊符号

Python 目前支援以下運算符:

+       -       *       **      //      /       %       <<      >>      &       |       ^
+=      -=      *=      **=     //=     /=      %=      <<=     >>=     &=      |=      ^=
~       <       >       <=      >=      ==      !=      <>
      

下邊的這些可以作為表達式,清單,字典,以及語句不同部分的分隔符号:

(    )      [    ]      {    }      ,      :      .      `      =      ;
      

比如,等号(=),作為對象名和所配置設定值之間的分隔符;逗号(,)用來分隔函數參數、清單或tuple中的元素;小數點(.)用在浮點數和擴充切片操作中的省略符(...),

下邊這些特殊符号也在語句中使用:

' " # / @

注:Python 2.4 中新增了 @ 符号用作函數修飾符 ---Wei Zhong 
      

字元$、?不能在程式語句中出現,但是可以出現在字元串中。

1.5. 文檔字元串

如果一個子產品、類、或函數體的第一個語句是未命名一個字元串,該字元串就自動成為該對象的文檔字元串( DocStrings ),如下例:

<script type="text/javascript"> document.write(' Toggle line numbers '); </script> Toggle line numbers

1 def fact(n):
   2     "This function computes a factorial"
   3     if (n <= 1): return 1
   4     else: return n*fact(n-1)
      

代碼浏覽及文檔生成工具經常用到文檔字元串。通過通路一個對象的__doc__屬性,你可以得到文檔字元串:

這個 __doc__ 屬性竟然是可寫的。--WeiZhong
      
>>> print fact._ _doc_ _
This function computes a factorial
>>>
      

文檔字元串的縮進必須與定義中的其他語句一緻。此外,在不同行出現的多個未命名字元串不會自動連結成一個字元串,即使他們緊挨着。(注意:傳回的文檔字元串僅僅是第一個字元串,這與前邊講到的字元串的自動連結有所不同,注意差別)。