看例子,學 Python(一)

看例子,學 Python(一)

看例子,學 Python(二)
看例子,學 Python(三)python

很難說,這篇代碼比文字還多的文章,是否適合初學者。
它源於我的筆記,涉及的可能是簡單核心的概念,也許須要一些編程基礎才能快速理解。
內容方面,力求按部就班,避開細枝末節,注重原理和示例的連續性,儘可能不羅列特性,點到即止。編程

說明:本文僅限於 Python 3。segmentfault

Hello, Python!

Hello, Python! 開始,經過一系列不一樣實現,簡單介紹字符串、函數等概念。數據結構

初版

print("Hello, Python!")

print 是一個內置函數;在 Python 2 裏,print 是一個語句(statement)。
字符串由引號表示,這一點與其它語言相似。
語句末尾不須要結尾符(好比 C 系列語言的分號)。app

第二版

print("Hello, " + "Python!")
print("Hello, " * 3 + "Python!")

字面字符串即爲對象。
操做符 +* 都對字符串作了重載。編輯器

第三版

print('Hello, "Python"!')

字符串能夠用雙引號,也能夠用單引號。順帶也可看出 Python 並無字符類型(char)。
經過單、雙引號的恰當使用,能夠避免沒必要要的字符轉義(escape)。上例若改用雙引號,則裏面的 " 就須要轉義了:函數

print("Hello, \"Python\"!")

第四版

def say_hello():
    print('Hello, Python!')

函數定義由 def 關鍵字指定。
函數的命名習慣上爲小寫下劃線(xxx\_yyy\_zzz),變量名也是,類名則是駝峯狀(XxxYyyZzz)。
Python 以【縮進】組織代碼塊,沒有 C 系列語言的花括號,也沒有 Ruby 那樣的 end 語句。
使用縮進的優勢是,代碼風格比較單一,也就比較統一,沒有諸如 { 是否另起一行的爭論;缺點是沒法自動縮進,不但給編輯器出了難題,也使代碼分享變得相對困難,由於縮進一變,程序就不對了。性能

Python 概覽

對應於官方教程第三章。
簡單介紹字符串、列表等概念,爲後續內容作準備。ui

字符串

下面由 >>> 打頭的代碼,表示是在交互模式下的演示。
打開命令行,鍵入 python,便可進入交互模式。命令行

>>> s = "Hello!"
>>> s
'Hello!'

內建函數 len

字符串並無方法(size 或 length)返回長度,取而代之的是內建函數 len

>>> len("Hello!")
6

其它序列類型(sequence type)也是如此。

遍歷

做爲一種序列類型,字符串能夠直接用 for 遍歷。

>>> for c in "Hello!": print(c)
...
H
e
l
l
o
!

注意這裏的變量 c,雖然表示的是單個字符,其實倒是字符串。前面已經說過,Python 沒有字符類型。

類型

經過幾個內建函數,在交互模式下作一些試驗。

函數 type:查看對象類型:

>>> type("Hello!")
<type 'str'>

函數 help:查看類型或函數的幫助信息:

>>> help(str)
Help on class str in module builtins:

class str(object)
 |  str(object='') -> str
<省略>

查看 help 本身的幫助信息:

>>> help(help)
Help on _Helper in module _sitebuiltins object:
<省略>

函數 dir:列出類的屬性:

>>> dir(str)
['__add__', '__class__', '__contains__', <省略>]

不妨看看 dir 又是什麼:

>>> help(dir)
Help on built-in function dir in module builtins:
<省略>

類型之間能夠比較:

>>> type("hello") == str
True

可是通常不這麼用,通常用 isinstance,由於後者會考慮到類的繼承關係:

>>> isinstance("hello", str)
True

不出意外,類型自身也有類型:

>>> type(str)
<class 'type'>

這幾個內建函數,很是稱手,後面會常常用到。

不可變性

嘗試像 C/C++ 那樣對單個字符賦值:

>>> s = "Hello!"
>>> s[-1] = '.'  # -1 表示倒數第一個(也即最後一個)字符的下標
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

錯誤信息顯示:str 對象不支持元素賦值。

方法 replace 也同樣,不會改變原來的字符串,而是返回一個替換後的新字符串:

>>> help(str.replace)

replace(...)
    S.replace(old, new[, count]) -> string

    Return a copy of string S with all occurrences of substring
    old replaced by new.  If the optional argument count is
    given, only the first count occurrences are replaced.
>>> s = "Hello!"
>>> s.replace('!', '.')
"Hello."
>>> s
"Hello!"  # 原對象並無改變

列表

列表(list)是最經常使用的數據結構,相似於 C++ 的 std::vector

定義

>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
>>> type(squares)
<class 'list'>

索引

列表的底層實現並不是鏈表(linked list),因此索引的性能仍是不錯的。
比較特別的地方在於,索引的下標能夠爲負數,好比前面提到 -1 表示倒數第一個元素。

>>> squares[0]
1
>>> squares[-1]
25

切片

切片(slice)截取列表的一段。

>>> squares[1:4]
[4, 9, 16]

字符串也能夠切片。
固然,切片返回新序列,原序列保持不變。

拷貝

由於 Python 的對象是引用計數的,因此要拷貝一個列表,不能簡單的賦值,可是能夠用切片間接實現:

>>> squares[:]
[1, 4, 9, 16, 25]

不指定起始和結束下標,就切片整個列表。至關於 squares[0:]squares[0:len(squares)]

拼接

拼接兩個列表,直接相加便可。

>>> squares + [36, 48]
[1, 4, 9, 16, 25, 36, 48]

如前所述,Python 有操做符重載的概念,與 C++ 不無類似之處。

可變性

與字符串不一樣,列表是可變的,能夠被修改。

>>> squares[6] = 49
>>> squares.append(64)
>>> squares.pop()
49
>>> squares
[1, 4, 9, 16, 25, 36]

編程初步

以「斐波那契數列」爲例,介紹基本的控制語句、函數定義。

斐波那契數列

0, 1, 1, 2, 3, 5, 8, ...
a  b
   a, b
      a, b

交互模式下的演示

打印 100 之內的數列:

>>> a, b = 0, 1
>>> while a < 100:
...     print(a, end='')
...     a, b = b, a+b
...
0 1 1 2 3 5 8 13 21 34 55 89 >>>

如下幾點值得一提:

  • Python 支持多變量賦值(multiple assignment),好比 a, b = 0, 1,能夠簡化代碼,更讓 swap 操做變得異常簡單:a, b = b, a
  • while 語句與其它語言相似。
  • print 函數指定 end 參數爲空就再也不換行了,end 缺省爲 '\n'

函數定義

函數由關鍵字 def 定義。
把剛纔寫在交互模式下代碼,封裝成 fib 函數,並移到文件 mymath.py 中:

def fib(n):
    "Print a Fibonacci series up to n."
    
    a, b = 0, 1
    while a < n:
        print(a, end='')
        a, b = b, a+b

那麼,mymath 就是一個模塊(module)。
關於模塊,Python 是這樣定義的:

A module is a file containing Python definitions and statements.

函數對象

對於模塊,咱們暫時先不作深究,知道經過 import 語句來使用便可,就好像 Java 的 import 或 C++ 的 #include 同樣。

>>> import mymath
>>> mymath.fib
<function fib at 0x7fd1d6ec25f0>
>>> mymath.fib(100)
0 1 1 2 3 5 8 13 21 34 55 89
>>> fib = mymath.fib
>>> fib(100)
0 1 1 2 3 5 8 13 21 34 55 89

函數也是對象,能夠賦值給變量,做爲參數傳遞。這比 C/C++ 裏的函數指針更強大。

文檔字符串 (docstring)

前面定義 fib 時,函數體前有一個字符串:Print a Fibonacci series up to n,不知道你注意沒有?
它就是文檔字符串,既能夠充當註釋,又是函數對象的一部分,你能夠經過屬性 __doc__ 訪問:

>>> fib.__doc__
'Print a Fibonacci series up to n.'

文檔字符串的功能不言而喻,它爲函數 help 提供了萃取信息的通道。

>>> help(fib)
Help on function fib in module mymath:

fib(n)
    Print a Fibonacci series up to n.

若是文檔字符串有多行,可使用三重引號的字符串:

def fib(n):
    """Print a Fibonacci series up to n.
    E.g., fib(10) prints:
        0 1 1 2 3 5 8
    """

函數返回值

只要是函數,都有返回值,沒有明確指定返回值的,就返回 None
None 是 Python 的空值,至關於 C++ 的 NULL 或 Java 的 null

>>> fib(0)
>>> print(fib(0))
None

讓 fib 返回列表

直接打印結果的函數,並非一個好的設計,對於 fib 來講,把結果以列表返回要實用得多。

def fib(n):
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

另外一種實現

改寫 fib 函數,返回數列中的第 N 個數。

def fib(n):
    a, b = 0, 1
    if n <= 0:
        return 0
    if n == 1:
        return 1
    while n > 1:
        a, b = b, a+b
        n -= 1
    return b

Python 的 if else 縮寫爲 elif
Python 沒有 ++-- 操做符,可是有 +=-=

遞歸版

遞歸和循環比較,遞歸易理解,循環更高效。

def fib(n):
    if n <= 0:
        return 0
    if n == 1:
        return 1
    return fib(n-1) + fib(n-2)

階乘(練習)

各位能夠暫停一下,拿階乘(factorial)練練手,下面先給出輪廓:

def fac(n):
    """ ...
    >>> fac(4)
    24
    """
    pass

pass 是佔位符,用來標記空代碼塊,純粹爲了經過「編譯」。

參考實現:

def fac(n):
    """C-style implementation"""
    result = 1
    while n > 1:
        result = result * n
        n -= 1
    return result

使用 range 實現階乘

range 表示一段範圍,好比 range(2, n) 就表示從 2 一直到 n-1(不包括 n)。

def fac(n):
    result = 1
    for i in range(2, n+1):
        result *= i
    return result

for

回到前面遍歷字符串的演示:

>>> s = "Hello!"
>>> for c in s: print(c)

若是須要索引,用 enumerate

>>> for i, c in enumerate(s):
...     print("s[{}] = {}".format(i, c))
...
s[0] = H
s[1] = e
s[2] = l
s[3] = l
s[4] = o
s[5] = !

range 也能達到目的:

>>> for i in range(len(s)):
...     print("s[{}] = {}".format(i, s[i]))

range

再看幾個 range 的例子:

>>> range(10)  # 起點默認爲 0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(0, 10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(0, 10, 3)  # 步長爲 3 
[0, 3, 6, 9]

最後再來看一下 range 的幫助信息:

>>> help(range)

range(...)
    range(stop) -> list of integers
    range(start, stop[, step]) -> list of integers
    <省略>

如前所述,函數 help 是很是稱手的。

看例子,學 Python(二)
看例子,學 Python(三)

相關文章
相關標籤/搜索