python 2.7 中文教程-4:編程基礎

流程控制

除了前面介紹的 while 語句,Python還更多的流程控制工具。

if語句

>>> x = int(raw_input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
...     x = 0
...     print 'Negative changed to zero'
... elif x == 0:
...     print 'Zero'
... elif x == 1:
...     print 'Single'
... else:
...     print 'More'
...
More

可能會有零到多個elif部分,else是可選的。關鍵字‘elif‘是‘else if’的縮寫,可避免過深的縮進。 if ... elif ... elif序列用於替代其它語言中的switch或case語句。python中沒有case語言,可以考慮用字典或者elif語句替代。

 

for語句

Python的for語句針對序列(列表或字符串等)中的子項進行循環,按它們在序列中的順序來進行迭代。
 

>>> # Measure some strings:
... words = ['cat''window''defenestrate']
>>> for w in words:
...     print w, len(w)
...
cat 3
window 6
defenestrate 12

在迭代過程中修改迭代序列不安全,可能導致部分元素重複兩次,建議先拷貝:
 

>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate''cat''window''defenestrate']

range()函數

內置函數 range()生成等差數值序列:

>>> range(10)
[0123456789]

range(10) 生成了一個包含10個值的鏈表,但是不包含最右邊的值。默認從0開始,也可以讓range 從其他值開始,或者指定不同的增量值(甚至是負數,有時也稱"步長"):

>>> range(510)
[56789]
>>> range(0103)
[0369]
>>> range(-10, -100, -30)
[-10, -40, -70]
>>> range(-10, -10030)
[]

如果迭代時需要索引和值可結合使用range()和len():

>>> a = ['Mary''had''a''little''lamb']
>>> for i in range(len(a)):
...     print i, a[i]
...
0 Mary
1 had
2 a
3 little
4 lamb

不過使用enumerate()更方便,參見後面的介紹。

break和continue語句及循環中的else子句

break語句和C中的類似,用於終止當前的for或while循環。

循環可能有else 子句;它在循環迭代完整個列表(對於 for)後或執行條件爲false(對於 while)時執行,但循環break時不會執行。這點和try...else而不是if...else相近。請看查找素數的程序:
 

>>> for n in range(210):
...     for x in range(2, n):
...         if n % x == 0:
...             print n, 'equals', x, '*', n/x
...             break
...     else:
...         # loop fell through without finding a factor
...         print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

continue語句也是從C而來,它表示退出當次循環,繼續執行下次迭代。通常可以用if...else替代,請看查找偶數的實例:
 

>>> for num in range(210):
...     if num % 2 == 0:
...         print "Found an even number", num
...         continue
...     print "Found a number", num
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

pass

pass語句什麼也不做。它語法上需要,但是實際什麼也不做場合,也常用語以後預留以後擴展。例如:
 

>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...
>>> class MyEmptyClass:
...     pass
...
>>> def initlog(*args):
...     pass   # Remember to implement this!
...

定義函數

菲波那契數列的函數:
 

>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 01
...     while a < n:
...         print a,
...         a, b = b, a+b
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

關鍵字def引入函數定義,其後有函數名和包含在圓括號中的形式參數。函數體語句從下一行開始,必須縮進的。
函數體的第一行語句可以是可選的字符串文本,即文檔字符串。有些工具通過docstrings 自動生成文檔,或者讓用戶通過代碼交互瀏覽;添加文檔字符串是個很好的習慣。
函數執行時生成符號表用來存儲局部變量。 確切地說,所有函數的變量賦值都存儲在局部符號表。 變量查找的順序,先局部,然後逐級向上,再到全局變量,最後內置名。全局變量可在局部直接飲用,但不能直接賦值(除非用global聲明),儘管他們可以被引用, 因爲python在局部賦值會重新定義一個本地變量。
函數的實際參數在調用時引入局部符號表,也就是說是傳值調用(值總是對象引用, 而不是該對象的值)。
函數定義會在當前符號表內引入函數名。 函數名的值爲用戶自定義函數的類型,這個值可以賦值給其他變量當做函數別名使用。

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

沒有return語句的函數也會返回None。 解釋器一般不會顯示None,除非用print打印。

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

從函數中返回
 

>>> def fib2(n): # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 01
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[01123581321345589]

return語句從函數中返回值,不帶表達式的return返回None。過程結束後也會返回 None 。

語句result.append(b)稱爲調用了列表的方法。方法是屬於對象的函數,如obj.methodename,obj 是個對象(可能是一個表達式),methodname是對象的方法名。不同類型有不同的方法。不同類型可能有同名的方法。append()向鏈表尾部附加元素,等同於 result = result + [b] ,不過更有效。

深入Python函數定義

python的函數參數有三種方式。

默認參數

最常用的方式是給參數指定默認值,調用時就可以少傳參數:
 

def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
    while True:
        ok = raw_input(prompt)
        if ok in ('y''ye''yes'):
            return True
        if ok in ('n''no''nop''nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise IOError('refusenik user')
        print complaint

調用方式:

    只給出必選參數: ask_ok('Do you really want to quit?')
    給出一個可選的參數: ask_ok('OK to overwrite the file?', 2)
    給出所有的參數: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

in關鍵字測定序列是否包含指定值。

默認值在函數定義時傳入,如下所示:
 

i = 5
def f(arg=i):
    print arg
i = 6
f()

上例顯示5。

注意: 默認值只賦值一次。當默認值是可變對象(比如列表、字典或者大多數類的實例)時結果會不同。實例:
 

def f(a, L=[]):
    L.append(a)
    return L
print f(1)
print f(2)
print f(3)
執行結果:
[1]
[12]
[123]

規避方式:
 

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

關鍵字參數


關鍵字參數 的形式: keyword = value。

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

有效調用:
 

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million''bereft of life''jump')         # 3 positional arguments
parrot('a thousand'state='pushing up the daisies')  # 1 positional, 1 keyword

無效調用
 

parrot()                     # 沒有必選參數
parrot(voltage=5.0, 'dead')  # 關鍵參數後面有非關鍵字參數
parrot(110voltage=220)     # 同一參數重複指定值
parrot(actor='John Cleese')  # 不正確的關鍵字參數名

關鍵字參數在位置參數之後,多個關鍵字參數的順序先後無關,一個參數只能指定一次值,報錯實例:
 

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
  File "<stdin>", line 1in ?
TypeError: function() got multiple values for keyword argument 'a'

最後一個如果前有兩個星號(比如name)接收一個字典,存儲形式參數沒有定義的參數名和值。類似的單個星號比如*name表示接受一個元組。
 

def cheeseshop(kind, *arguments, **keywords):
    print "-- Do you have any", kind, "?"
    print "-- I'm sorry, we're all out of", kind
    for arg in arguments:
        print arg
    print "-" * 40
    keys = sorted(keywords.keys())
    for kw in keys:
        print kw, ":", keywords[kw]

調用
 

cheeseshop("Limburger""It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper='Michael Palin',
           client="John Cleese",
           sketch="Cheese Shop Sketch")

執行:
 

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch

注意參數順序是隨機的,可以使用sort排序。

任意參數列表

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

參數列表解包

把列表或元組拆分成多個並列的參數。

>>> range(36)             # normal call with separate arguments
[345]
>>> args = [36]
>>> range(*args)            # call with arguments unpacked from a list
[345]

同樣的字典可以用兩個星號解包:
 

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print "-- This parrot wouldn't", action,
...     print "if you put", voltage, "volts through it.",
...     print "E's", state, "!"
...
>>> d = {"voltage""four million""state""bleedin' demised""action""VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

 

Lambda表達式

lambda關鍵字可創建短小的匿名函數,函數體只有一行,創建時就可使用。比如求和:lambda a, b: a+b。通常不建議使用:
 

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

除了返回表達式,lambda還可以用作函數參數。

>>> pairs = [(1'one'), (2'two'), (3'three'), (4'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4'four'), (1'one'), (3'three'), (2'two')](1)

文檔字符串

文檔字符串的內容和格式建議如下。

第一簡短介紹對象的目的。不能描述對象名和類型等其他地方能找到的信息,首字母要大寫。
如果文檔字符串有多行,第二行爲空行以分隔概述和其他描述。描述介紹調用約定、邊界效應等。
Python解釋器不會從多行文檔字符串中去除縮進,要用工具來處理。約定如下:第一行後的第一個非空行決定了整個文檔的縮進。實例:
 

>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn't do anything.
...     """
...     pass
...
>>> print my_function.__doc__
Do nothing, but document it.
    No, really, it doesn't do anything.

編碼風格


建議遵守PEP8,高可讀性,部分要點如下:

    使用4空格縮進,而非tab。
    每行不超過79個字符。
    使用空行分隔函數和類,以及函數中的大代碼塊。
    可能的話,註釋佔一行
    使用文檔字符串
    操作符前後有空格,逗號後有空格,但是括號兩側無空格。如: a = f(1, 2) + g(3, 4) 。
    統一函數和類命名。類名用首字母大寫的駝峯式,比如CamelCase。函數和方法名用小寫和下劃線組成:lower_case_with_underscores。類中使用self。
    國際化時不要使用花哨的編碼。

另: https://pypi.python.org/pypi/autopep8能把代碼調整爲符合pep8,https://pypi.python.org/pypi/pep8能檢查是否符合pep8,推薦使用。

發佈了28 篇原創文章 · 獲贊 21 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章