Python 3 入門,最全面的基礎看這篇就夠了!

 

基礎語法

 

運行 Python

 

交互式解釋器

 

在命令行窗口執行python後,進入 Python 的交互式解釋器。python

 

exit() 或 Ctrl + D 組合鍵退出交互式解釋器。c++

 

命令行腳本

 

在命令行窗口執行python script-file.py,以執行 Python 腳本文件。express

 

指定解釋器

 

若是在 Python 腳本文件首行輸入#!/usr/bin/env python,那麼能夠在命令行窗口中執行/path/to/script-file.py以執行該腳本文件。編程

 

注:該方法不支持 Windows 環境。數組

 

編碼

 

默認狀況下,3.x 源碼文件都是 UTF-8 編碼,字符串都是 Unicode 字符。網絡

 

也能夠手動指定文件編碼:數據結構

# -*- coding: utf-8 -*-

 

或者閉包

 

# encoding: utf-8

 

注意: 該行標註必須位於文件第一行。app

 

標識符

 

  • 第一個字符必須是英文字母或下劃線 _ 。dom

 

  • 標識符的其餘的部分由字母、數字和下劃線組成。

 

  • 標識符對大小寫敏感。

 

注:從 3.x 開始,非 ASCII 標識符也是容許的,但不建議。

 

保留字

 

保留字即關鍵字,咱們不能把它們用做任何標識符名稱。

 

Python 的標準庫提供了一個 keyword 模塊,能夠輸出當前版本的全部關鍵字:

>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

 

註釋

 

單行註釋採用#,多行註釋採用'''或"""。

# 這是單行註釋

'''
這是多行註釋

這是多行註釋
'''

"""
這也是多行註釋

這也是多行註釋
"""

 

行與縮進

 

Python 最具特點的就是使用縮進來表示代碼塊,不須要使用大括號 {}。 

 

縮進的空格數是可變的,可是同一個代碼塊的語句必須包含相同的縮進空格數,縮進不一致,會致使運行錯誤。

 

多行語句

 

Python 一般是一行寫完一條語句。

 

但若是語句很長,咱們可使用反斜槓\來實現多行語句。

 

total = item_one + \
     item_two + \
     item_three

 

在 [], {}, 或 () 中的多行語句,不須要使用反斜槓\。

在學習中有迷茫不知如何學習的朋友小編推薦一個學Python的學習q u n 227 435 450不管你是大牛仍是小白,是想轉行仍是想入行均可以來了解一塊兒進步一塊兒學習!內有開發工具,不少乾貨和技術資料分享!

空行

 

函數之間或類的方法之間用空行分隔,表示一段新的代碼的開始。

 

類和函數入口之間也用一行空行分隔,以突出函數入口的開始。

 

空行與代碼縮進不一樣,空行並非 Python 語法的一部分。

 

書寫時不插入空行,Python 解釋器運行也不會出錯。

 

可是空行的做用在於分隔兩段不一樣功能或含義的代碼,便於往後代碼的維護或重構。

 

記住:空行也是程序代碼的一部分。

 

等待用戶輸入

 

input函數能夠實現等待並接收命令行中的用戶輸入。

content = input("\n\n請輸入點東西並按 Enter 鍵\n")
print(content)

 

同一行寫多條語句

 

Python 能夠在同一行中使用多條語句,語句之間使用分號;分割。

import sys; x = 'hello world'; sys.stdout.write(x + '\n')

 

多個語句構成代碼組

 

縮進相同的一組語句構成一個代碼塊,咱們稱之代碼組。

 

if、while、defclass這樣的複合語句,首行以關鍵字開始,以冒號:結束,該行以後的一行或多行代碼構成代碼組。

 

咱們將首行及後面的代碼組稱爲一個子句(clause)。

 

print 輸出

 

print 默認輸出是換行的,若是要實現不換行須要在變量末尾加上end=""或別的非換行符字符串:

print('123') # 默認換行
print('123', end = "") # 不換行

 

import 與 from…import

 

在 Python 用 import 或者 from...import 來導入相應的模塊。

 

將整個模塊導入,格式爲:import module_name

 

從某個模塊中導入某個函數,格式爲:from module_name import func1

 

從某個模塊中導入多個函數,格式爲:from module_name import func1, func2, func3

 

將某個模塊中的所有函數導入,格式爲:from module_name import *

 

運算符

 

算術運算符

 

運算符 描述
+
-
*
/
% 取模
**
// 取整除

 

比較運算符

 

運算符 描述
== 等於
!= 不等於
> 大於
< 小於
>= 大於等於
<= 小於等於

 

賦值運算符

 

 

運算符 描述
= 簡單的賦值運算符
+= 加法賦值運算符
-= 減法賦值運算符
*= 乘法賦值運算符
/= 除法賦值運算符
%= 取模賦值運算符
**= 冪賦值運算符
//= 取整除賦值運算符

 

位運算符

 

 

邏輯運算符

 

 

成員運算符

 

 

身份運算符

 

 

運算符優先級

 

 

具備相同優先級的運算符將從左至右的方式依次進行,用小括號()能夠改變運算順序。

 

變量

 

變量在使用前必須先」定義」(即賦予變量一個值),不然會報錯:

>>> name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined

 

數據類型

 

布爾(bool)

 

只有 True 和 False 兩個值,表示真或假。

 

數字(number)

 

整型(int)

 

整數值,可正數亦可複數,無小數。 

 

3.x 整型是沒有限制大小的,能夠看成 Long 類型使用,因此 3.x 沒有 2.x 的 Long 類型。

 

浮點型(float)

 

浮點型由整數部分與小數部分組成。

 

浮點型也可使用科學計數法表示(2.5e2 = 2.5 x 10^2 = 250)

 

複數(complex)

 

複數由實數部分和虛數部分構成,能夠用a + bj,或者complex(a,b)表示。

 

複數的實部 a 和虛部 b 都是浮點型。

 

數字運算

 

  • 不一樣類型的數字混合運算時會將整數轉換爲浮點數

 

  • 在不一樣的機器上浮點運算的結果可能會不同

 

  • 在整數除法中,除法 / 老是返回一個浮點數。

 

      若是隻想獲得整數的結果,丟棄可能的分數部分,可使用運算符 //。

 

  • // 獲得的並不必定是整數類型的數,它與分母分子的數據類型有關係。

 

  • 在交互模式中,最後被輸出的表達式結果被賦值給變量 _,_ 是個只讀變量

 

數學函數

 

:如下函數的使用,需先導入 math 包。

 

 

隨機數函數

 

:如下函數的使用,需先導入 random 包。

 

 

三角函數

 

:如下函數的使用,需先導入 math 包。

 

 

數學常量

 

字符串(string)

 

  • 單引號和雙引號使用徹底相同。

 

  • 使用三引號('''或""")能夠指定一個多行字符串。

 

  • 轉義符(反斜槓\)能夠用來轉義,使用r可讓反斜槓不發生轉義。

 

      如r"this is a line with \n",則\n會顯示,並非換行。

 

  • 按字面意義級聯字符串。

 

      如"this " "is " "string"會被自動轉換爲this is string。

 

  • 字符串能夠用 + 運算符鏈接在一塊兒,用 * 運算符重複。

 

  • 字符串有兩種索引方式,從左往右以 0 開始,從右往左以 -1 開始。

 

  • 字符串不能改變。

 

  • 沒有單獨的字符類型,一個字符就是長度爲 1 的字符串。

 

  • 字符串的截取的語法格式以下:變量[頭下標:尾下標]。

 

轉義字符

 

 

字符串運算符

 

 

字符串格式化

 

在 Python 中,字符串格式化不是 sprintf 函數,而是用 % 符號。

 

例如:

print("我叫%s, 今年 %d 歲!" % ('小明', 10))

// 輸出:
我叫小明, 今年 10 歲!

 

格式化符號:

 

 

輔助指令:

 

 

Python 2.6 開始,新增了一種格式化字符串的函數 str.format(),它加強了字符串格式化的功能。

 

多行字符串

 

  • 用三引號(''' 或 """)包裹字符串內容

 

  • 多行字符串內容支持轉義符,用法與單雙引號同樣

 

  • 三引號包裹的內容,有變量接收或操做即字符串,不然就是多行註釋

 

實例:

string = '''
print(\tmath.fabs(-10))

print(\nrandom.choice(li))
'''


print(string)

 

輸出:

print(  math.fabs(-10))

print(
random.choice(li))

 

Unicode

 

在 2.x 中,普通字符串是以 8 位 ASCII 碼進行存儲的。

 

而 Unicode 字符串則存儲爲 16 位 Unicode 字符串,這樣可以表示更多的字符集。

 

使用的語法是在字符串前面加上前綴 u。

 

在 3.x 中,全部的字符串都是 Unicode 字符串。

 

字符串函數

 

 

字節(bytes)

 

在 3.x 中,字符串和二進制數據徹底區分開。

 

文本老是 Unicode,由 str 類型表示,二進制數據則由 bytes 類型表示。

 

Python 3 不會以任意隱式的方式混用 str 和 bytes,你不能拼接字符串和字節流,也沒法在字節流裏搜索字符串(反之亦然),也不能將字符串傳入參數爲字節流的函數(反之亦然)。

 

  • bytes 類型與 str 類型,兩者的方法僅有 encode() 和 decode() 不一樣。

 

  • bytes 類型數據需在常規的 str 類型前加個 b 以示區分,例如 b'abc'。

 

  • 只有在須要將 str 編碼(encode)成 bytes 的時候。

 

     好比:經過網絡傳輸數據;或者須要將 bytes 解碼(decode)成 str 的時候,      咱們纔會關注 str 和 bytes 的區別。

 

bytes 轉 str:

b'abc'.decode()
str(b'abc')
str(b'abc', encoding='utf-8')

 

str 轉 bytes:

'中國'.encode()
bytes('中國', encoding='utf-8')

 

列表(list)

 

  • 列表是一種無序的、可重複的數據序列,能夠隨時添加、刪除其中的元素。

 

  • 列表頁的每一個元素都分配一個數字索引,從 0 開始。

 

  • 列表使用方括號建立,使用逗號分隔元素。

 

  • 列表元素值能夠是任意類型,包括變量。

 

  • 使用方括號對列表進行元素訪問、切片、修改、刪除等操做,開閉合區間爲[)形式。

 

  • 列表的元素訪問能夠嵌套。

 

  • 方括號內能夠是任意表達式。

 

建立列表

hello = (1, 2, 3)
li = [1, "2", [3, 'a'], (1, 3), hello]

 

訪問元素

li = [1, "2", [3, 'a'], (1, 3)]
print(li[3])        # (1, 3)
print(li[-2])       # [3, 'a']

 

切片訪問

 

格式: list_name[begin:end:step] begin 表示起始位置(默認爲0),end 表示結束位置(默認爲最後一個元素),step 表示步長(默認爲1)。

 

hello = (1, 2, 3)
li = [1, "2", [3, 'a'], (1, 3), hello]

print(li)           # [1, '2', [3, 'a'], (1, 3), (1, 2, 3)]
print(li[1:2])      # ['2']
print(li[:2])       # [1, '2']
print(li[:])        # [1, '2', [3, 'a'], (1, 3), (1, 2, 3)]
print(li[2:])       # [[3, 'a'], (1, 3), (1, 2, 3)]
print(li[1:-1:2])   # ['2', (1, 3)]

 

訪問內嵌 list 的元素:

li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ['a', 'b', 'c']]

print(li[1:-1:2][1:3])      # (3, 5)
print(li[-1][1:3])          # ['b', 'c']
print(li[-1][1])            # b

 

修改列表

 

經過使用方括號,能夠很是靈活的對列表的元素進行修改、替換、刪除等操做。

li = [0, 1, 2, 3, 4, 5]
li[len(li) - 2] = 22    # 修改 [0, 1, 2, 22, 4, 5]
li[3] = 33              # 修改 [0, 1, 2, 33, 4, 5]
li[1:-1] = [9, 9]       # 替換 [0, 9, 9, 5]
li[1:-1] = []           # 刪除 [0, 5]

 

刪除元素

 

能夠用 del 語句來刪除列表的指定範圍的元素。

li = [0, 1, 2, 3, 4, 5]

del li[3]       # [0, 1, 2, 4, 5]
del li[2:-1]    # [0, 1, 5]

 

列表操做符

 

  • + 用於合併列表。

 

  • * 用於重複列表元素。

 

  • in 用於判斷元素是否存在於列表中。

 

  • for ... in ... 用於遍歷列表元素。

 

[1, 2, 3] + [3, 4, 5]           # [1, 2, 3, 3, 4, 5]
[1, 2, 3] * 2                   # [1, 2, 3, 1, 2, 3]
3 in [1, 2, 3]                  # True
for x in [1, 2, 3]: print(x)    # 1 2 3

 

列表函數

 

  • len(list) 列表元素個數

 

  • max(list) 列表元素中的最大值

 

  • min(list) 列表元素中的最小值

 

  • list(seq) 將元組轉換爲列表

 

li = [0, 1, 5]

max(li)     # 5
len(li)     # 3

 

注: 對列表使用 max/min 函數,2.x 中對元素值類型無要求,3.x 則要求元素值類型必須一致。

 

列表方法

 

  • list.append(obj)

在列表末尾添加新的對象

 

  • list.count(obj)

返回元素在列表中出現的次數

 

  • list.extend(seq)

在列表末尾一次性追加另外一個序列中的多個值

 

  • list.index(obj)

返回查找對象的索引位置,若是沒有找到對象則拋出異常

 

  • list.insert(index, obj)

將指定對象插入列表的指定位置

 

  • list.pop([index=-1]])

移除列表中的一個元素(默認最後一個元素),而且返回該元素的值

 

  • list.remove(obj)

移除列表中某個值的第一個匹配項

 

  • list.reverse()

反向排序列表的元素

 

  • list.sort(cmp=None, key=None, reverse=False)

對原列表進行排序,若是指定參數,則使用比較函數指定的比較函數

 

  • list.clear()

清空列表 還可使用 del list[:]、li = [] 等方式實現

 

  • list.copy()

複製列表 默認使用等號賦值給另外一個變量,其實是引用列表變量。若是要實現

 

列表推導式

 

列表推導式提供了從序列建立列表的簡單途徑。

 

一般應用程序將一些操做應用於某個序列的每一個元素,用其得到的結果做爲生成新列表的元素,或者根據肯定的斷定條件建立子序列。

 

每一個列表推導式都在 for 以後跟一個表達式,而後有零到多個 for 或 if 子句。

 

返回結果是一個根據表達從其後的 for 和 if 上下文環境中生成出來的列表。

 

若是但願表達式推導出一個元組,就必須使用括號。

 

將列表中每一個數值乘三,得到一個新的列表:

vec = [2, 4, 6]
[(x, x**2) for x in vec]
# [(2, 4), (4, 16), (6, 36)]

 

對序列裏每個元素逐個調用某方法:

freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
[weapon.strip() for weapon in freshfruit]
# ['banana', 'loganberry', 'passion fruit']

 

用 if 子句做爲過濾器:

vec = [2, 4, 6]
[3*x for x in vec if x > 3]
# [12, 18]
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
[x*y for x in vec1 for y in vec2]
# [8, 6, -18, 16, 12, -36, 24, 18, -54]
[vec1[i]*vec2[i] for i in range(len(vec1))]
# [8, 12, -54]

 

列表嵌套解析:

matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
new_matrix = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(new_matrix)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

 

元組(tuple)

 

  • 元組與列表相似,不一樣之處在於元組的元素不能修改

 

  • 元組使用小括號,列表使用方括號

 

  • 元組建立很簡單,只須要在括號中添加元素,並使用逗號隔開便可

 

  • 沒有 append(),insert() 這樣進行修改的方法,其餘方法都與列表同樣

 

  • 字典中的鍵必須是惟一的同時不可變的,值則沒有限制

 

  • 元組中只包含一個元素時,須要在元素後面添加逗號,不然括號會被看成運算符使用

 

訪問元組

 

訪問元組的方式與列表是一致的。 

 

元組的元素能夠直接賦值給多個變量,但變量數必須與元素數量一致。

a, b, c = (1, 2, 3)
print(a, b, c)

 

組合元組

 

元組中的元素值是不容許修改的,但咱們能夠對元組進行鏈接組合。

tup1 = (12, 34.56);
tup2 = ('abc', 'xyz')
tup3 = tup1 + tup2;
print (tup3)
# (12, 34.56, 'abc', 'xyz')

 

刪除元組

 

元組中的元素值是不容許刪除的,但咱們可使用 del 語句來刪除整個元組

元組函數

 

  • len(tuple) 元組元素個數

 

  • max(tuple) 元組元素中的最大值

 

  • min(tuple) 元組元素中的最小值

 

  • tuple(tuple) 將列表轉換爲元組

 

元組推導式

t = 1, 2, 3
print(t)
# (1, 2, 3)
u = t, (3, 4, 5)
print(u)
# ((1, 2, 3), (3, 4, 5))

 

字典(dict)

 

  • 字典是另外一種可變容器模型,可存儲任意類型對象

 

  • 字典的每一個鍵值(key=>value)對用冒號(:)分割,每一個對之間用逗號(,)分割,整個字典包括在花括號({})中

 

  • 鍵必須是惟一的,但值則沒必要

 

  • 值能夠是任意數據類型

 

  • 鍵必須是不可變的,例如:數字、字符串、元組能夠,但列表就不行

 

  • 若是用字典裏沒有的鍵訪問數據,會報錯

 

  • 字典的元素沒有順序,不能經過下標引用元素,經過鍵來引用

 

  • 字典內部存放的順序和 key 放入的順序是沒有關係的

 

格式以下:

d = {key1 : value1, key2 : value2 }

 

訪問字典

dis = {'a': 1, 'b': [1, 2, 3]}

print(dis['b'][2])

 

修改字典

dis = {'a': 1, 'b': [1, 2, 3], 9: {'name': 'hello'}}

dis[9]['name'] = 999
print(dis)

# {'a': 1, 9: {'name': 999}, 'b': [1, 2, 3]}

 

刪除字典

 

用 del 語句刪除字典或字典的元素。

dis = {'a': 1, 'b': [1, 2, 3], 9: {'name': 'hello'}}

del dis[9]['name']
print(dis)

del dis         # 刪除字典


# {'a': 1, 9: {}, 'b': [1, 2, 3]}

 

字典函數

 

  • len(dict) 計算字典元素個數,即鍵的總數

 

  • str(dict) 輸出字典,以可打印的字符串表示

 

  • type(variable) 返回輸入的變量類型,若是變量是字典就返回字典類型

 

  • key in dict 判斷鍵是否存在於字典中

 

字典方法

 

  • dict.clear()

刪除字典內全部元素

 

  • dict.copy()

返回一個字典的淺複製

 

  • dict.fromkeys(seq[, value])

建立一個新字典,以序列 seq 中元素作字典的鍵,value 爲字典全部鍵對應的初始值

 

  • dict.get(key, default=None)

返回指定鍵的值,若是值不在字典中返回默認值

 

  • dict.items()

以列表形式返回可遍歷的(鍵, 值)元組數組

 

  • dict.keys()

以列表返回一個字典全部的鍵

 

  • dict.values()

以列表返回字典中的全部值

 

  • dict.setdefault(key, default=None)

若是 key 在字典中,返回對應的值。

 

若是不在字典中,則插入 key 及設置的默認值 default,並返回 default ,default 默認值爲 None。

 

  • dict.update(dict2)

把字典參數 dict2 的鍵/值對更新到字典 dict 裏

dic1 = {'a': 'a'}
dic2 = {9: 9, 'a': 'b'}
dic1.update(dic2)
print(dic1)

# {'a': 'b', 9: 9}

 

  • dict.pop(key[,default])

刪除字典給定鍵 key 所對應的值,返回值爲被刪除的值。key 值必須給出,不然返回 default 值。

 

  • dict.popitem()

隨機返回並刪除字典中的一對鍵和值(通常刪除末尾對)

 

字典推導式

 

構造函數 dict() 直接從鍵值對元組列表中構建字典。若是有固定的模式,列表推導式指定特定的鍵值對:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}

 

此外,字典推導能夠用來建立任意鍵和值的表達式詞典:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

 

若是關鍵字只是簡單的字符串,使用關鍵字參數指定鍵值對有時候更方便:

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

 

集合(set)

 

集合是一個無序不重複元素的序列

 

建立集合

 

  • 可使用大括號 {} 或者 set() 函數建立集合

 

  • 建立一個空集合必須用 set() 而不是 {},由於 {} 是用來建立一個空字典

set(value) 方式建立集合,value 能夠是字符串、列表、元組、字典等序列類型

 

  • 建立、添加、修改等操做,集合會自動去重

{1, 2, 1, 3}            # {} {1, 2, 3}
set('12345')            # 字符串 {'3', '5', '4', '2', '1'}
set([1, 'a', 23.4])     # 列表 {1, 'a', 23.4}
set((1, 'a', 23.4))     # 元組 {1, 'a', 23.4}
set({1:1, 'b': 9})      # 字典 {1, 'b'}

 

添加元素

 

將元素 val 添加到集合 set 中,若是元素已存在,則不進行任何操做:

set.add(val)

 

也能夠用 update 方法批量添加元素,參數能夠是列表,元組,字典等:

set.update(list1, list2,...)

 

移除元素

 

若是存在元素 val 則移除,不存在就報錯:

set.remove(val)

 

若是存在元素 val 則移除,不存在也不會報錯:

set.discard(val)

 

隨機移除一個元素:

set.pop()

 

元素個數

 

與其餘序列同樣,能夠用 len(set) 獲取集合的元素個數。

 

清空集合

 

set.clear()

set = set()

 

判斷元素是否存在

val in set

 

其餘方法

 

  • set.copy()

複製集合

 

  • set.difference(set2)

求差集,在 set 中卻不在 set2 中

 

  • set.intersection(set2)

求交集,同時存在於 set 和 set2 中

 

  • set.union(set2)

求並集,全部 set 和 set2 的元素

 

  • set.symmetric_difference(set2)

求對稱差集,不一樣時出如今兩個集合中的元素

 

  • set.isdisjoint(set2)

若是兩個集合沒有相同的元素,返回 True

 

  • set.issubset(set2)

若是 set 是 set2 的一個子集,返回 True

 

  • set.issuperset(set2)

若是 set 是 set2 的一個超集,返回 True

 

集合計算

a = set('abracadabra')
b = set('alacazam')

print(a)                                  # a 中惟一的字母
# {'a', 'r', 'b', 'c', 'd'}


print(a - b)                              # 在 a 中的字母,但不在 b 中
# {'r', 'd', 'b'}


print(a | b)                              # 在 a 或 b 中的字母
# {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
print(a & b)                              # 在 a 和 b 中都有的字母
# {'a', 'c'}
print(a ^ b)                              # 在 a 或 b 中的字母,但不一樣時在 a 和 b 中
# {'r', 'd', 'b', 'm', 'z', 'l'}

 

集合推導式

a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)
# {'d', 'r'}

 

流程控制

 

if 控制

if 表達式1:
    語句
    if 表達式2:
        語句
    elif 表達式3:
        語句
    else:
        語句
elif 表達式4:
    語句
else:
    語句

 

一、每一個條件後面要使用冒號 :,表示接下來是知足條件後要執行的語句塊。

 

 二、使用縮進來劃分語句塊,相同縮進數的語句在一塊兒組成一個語句塊。 

 

三、在 Python 中沒有 switch - case 語句。

 

三元運算符:

<表達式1> if <條件> else <表達式2>

編寫條件語句時,應該儘可能避免使用嵌套語句。

 

嵌套語句不便於閱讀,並且可能會忽略一些可能性。

 

for 遍歷

for <循環變量> in <循環對象>:
    <語句1>
else:
    <語句2>

 

else 語句中的語句2只有循環正常退出(遍歷完全部遍歷對象中的值)時執行。

 

在字典中遍歷時,關鍵字和對應的值可使用 items() 方法同時解讀出來:

knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)

 

在序列中遍歷時,索引位置和對應值可使用 enumerate() 函數同時獲得:

for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)

 

同時遍歷兩個或更多的序列,可使用 zip() 組合:

questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
    print('What is your {0}?  It is {1}.'.format(q, a))

 

要反向遍歷一個序列,首先指定這個序列,而後調用 reversed() 函數:

for i in reversed(range(1, 10, 2)):
    print(i)

 

要按順序遍歷一個序列,使用 sorted() 函數返回一個已排序的序列,並不修改原值:

basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f)

 

while 循環

while<條件>:
    <語句1>
else:
    <語句2>

break、continue、pass

 

break 語句用在 while 和 for 循環中,break 語句用來終止循環語句。

 

即循環條件沒有 False 條件或者序列還沒被徹底遞歸完,也會中止執行循環語句。

 

continue 語句用在 while 和 for 循環中,continue 語句用來告訴 Python 跳過當前循環的剩餘語句,而後繼續進行下一輪循環。 

 

continue 語句跳出本次循環,而 break 跳出整個循環。

 

pass 是空語句,是爲了保持程序結構的完整性。

 

pass 不作任何事情,通常用作佔位語句。

 

迭代器

 

  • 迭代器是一個能夠記住遍歷的位置的對象。

 

  • 迭代器對象從集合的第一個元素開始訪問,直到全部的元素被訪問完結束。

 

迭代器只能往前不會後退。

 

  • 迭代器有兩個基本的方法:iter() 和 next()

 

  • 字符串,列表或元組對象均可用於建立迭代器。

 

迭代器能夠被 for 循環進行遍歷:

li = [1, 2, 3]
it = iter(li)
for val in it:
    print(val)

 

迭代器也能夠用 next() 函數訪問下一個元素值:

import sys

li = [1,2,3,4]
it = iter(li)

while True:
    try:
        print (next(it))
    except StopIteration:
        sys.exit()

 

生成器

 

  • 在 Python 中,使用了 yield 的函數被稱爲生成器(generator)。

 

  • 跟普通函數不一樣的是,生成器是一個返回迭代器的函數,只能用於迭代操做。

 

更簡單點理解生成器就是一個迭代器。

 

  • 在調用生成器運行的過程當中,每次遇到 yield 時函數會暫停並保存當前全部的運行信息,返回 yield 的值,並在下一次執行 next() 方法時從當前位置繼續運行。

 

  • 調用一個生成器函數,返回的是一個迭代器對象。

import sys

def fibonacci(n): # 生成器函數 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1


f = fibonacci(10) # f 是一個迭代器,由生成器返回生成

while True:
    try:
        print(next(f))
    except StopIteration:
        sys.exit()

 

函數

 

自定義函數

 

函數(Functions)是指可重複使用的程序片斷。

 

它們容許你爲某個代碼塊賦予名字,容許你經過這一特殊的名字在你的程序任何地方來運行代碼塊,並可重複任何次數。

 

這就是所謂的調用(Calling)函數。

 

  • 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。

 

  • 任何傳入參數和自變量必須放在圓括號中間,圓括號之間能夠用於定義參數。

 

  • 函數的第一行語句能夠選擇性地使用文檔字符串—用於存放函數說明。

 

  • 函數內容以冒號起始,而且縮進。

 

  • return [表達式] 結束函數,選擇性地返回一個值給調用方。

 

不帶表達式的 return 至關於返回 None。

 

  • return 能夠返回多個值,此時返回的數據未元組類型。

 

  • 定義參數時,帶默認值的參數必須在無默認值參數的後面。

 

def 函數名(參數列表):
    函數體

 

參數傳遞

 

在 Python 中,類型屬於對象,變量是沒有類型的:

a = [1,2,3]

a = "Runoob"

 

以上代碼中,[1,2,3] 是 List 類型,」Runoob」 是 String 類型。

 

而變量 a 是沒有類型,她僅僅是一個對象的引用(一個指針),能夠是指向 List 類型對象,也能夠是指向 String 類型對象。

 

可更改與不可更改對象

 

在 Python 中,字符串,數字和元組是不可更改的對象。

 

而列表、字典等則是能夠修改的對象。

 

  • 不可變類型:變量賦值 a=5 後再賦值 a=10,這裏實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,至關於新生成了a。

 

  • 可變類型:變量賦值 la=[1,2,3,4] 後再賦值 la[2]=5 ,則是將 list la 的第三個元素值更改,自己la沒有動,只是其內部的一部分值被修改了。

 

Python 函數的參數傳遞:

 

  • 不可變類型:相似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象自己。

 

好比在 fun(a)內部修改 a 的值,只是修改另外一個複製的對象,不會影響 a 自己。

 

  • 可變類型:相似 c++ 的引用傳遞,如 列表,字典。

 

如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響

 

Python 中一切都是對象,嚴格意義咱們不能說值傳遞仍是引用傳遞,咱們應該說傳不可變對象和傳可變對象。

 

參數

 

必需參數

 

必需參數須以正確的順序傳入函數。

 

調用時的數量必須和聲明時的同樣。

 

關鍵字參數

 

關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來肯定傳入的參數值。 

 

使用關鍵字參數容許函數調用時參數的順序與聲明時不一致,由於 Python 解釋器可以用參數名匹配參數值。

 

def print_info(name, age):
    "打印任何傳入的字符串"
    print("名字: ", name)
    print("年齡: ", age)
    return
print_info(age=50, name="john")

 

默認參數

 

調用函數時,若是沒有傳遞參數,則會使用默認參數。

 

def print_info(name, age=35):
    print ("名字: ", name)
    print ("年齡: ", age)
    return


print_info(age=50, name="john")
print("------------------------")
print_info(name="john")

 

不定長參數

 

  • 加了星號 * 的參數會以元組的形式導入,存放全部未命名的變量參數。

 

  • 若是在函數調用時沒有指定參數,它就是一個空元組。

 

咱們也能夠不向函數傳遞未命名的變量。

 

def print_info(arg1, *vartuple):
    print("輸出: ")
    print(arg1)
    for var in vartuple:
        print (var)
    return
print_info(10)
print_info(70, 60, 50)

 

  • 加了兩個星號 ** 的參數會以字典的形式導入,變量名爲鍵,變量值爲字典元素值。

 

def print_info(arg1, **vardict):
    print("輸出: ")
    print(arg1)
    print(vardict)
print_info(1, a=2, b=3)

 

匿名函數

 

Python 使用 lambda 來建立匿名函數。

 

所謂匿名,意即再也不使用 def 語句這樣標準的形式定義一個函數。

 

lambda 只是一個表達式,函數體比 def 簡單不少。

 

 lambda 的主體是一個表達式,而不是一個代碼塊。

 

僅僅能在 lambda 表達式中封裝有限的邏輯進去。 

 

lambda 函數擁有本身的命名空間,且不能訪問本身參數列表以外或全局命名空間裏的參數。 

 

雖然 lambda 函數看起來只能寫一行,卻不等同於 C 或 C++ 的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增長運行效率。

 

# 語法格式
lambda [arg1 [,arg2,.....argn]]:expression

 

變量做用域

 

  • L (Local) 局部做用域

 

  • E (Enclosing) 閉包函數外的函數中

 

  • G (Global) 全局做用域

 

  • B (Built-in) 內建做用域

 

以 L –> E –> G –> B 的規則查找,即:在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內建中找。

 

Python 中只有模塊(module),類(class)以及函數(def、lambda)纔會引入新的做用域,其它的代碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的做用域的。

 

也就是說這些語句內定義的變量,外部也能夠訪問。

 

定義在函數內部的變量擁有一個局部做用域,定義在函數外的擁有全局做用域。

 

局部變量只能在其被聲明的函數內部訪問,而全局變量能夠在整個程序範圍內訪問。

 

調用函數時,全部在函數內聲明的變量名稱都將被加入到做用域中。

 

當內部做用域想修改外部做用域的變量時,就要用到global和nonlocal關鍵字。

 

num = 1
def fun1():
    global num  # 須要使用 global 關鍵字聲明
    print(num) 
    num = 123
    print(num)
fun1()

 

若是要修改嵌套做用域(enclosing 做用域,外層非全局做用域)中的變量則須要 nonlocal 關鍵字。

 

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal關鍵字聲明
        num = 100
        print(num)
    inner()
    print(num)
outer()

 

模塊

 

編寫模塊有不少種方法。

 

其中最簡單的一種即是建立一個包含函數與變量、以 .py 爲後綴的文件。

 

另外一種方法是使用撰寫 Python 解釋器自己的本地語言來編寫模塊。

 

舉例來講,你可使用 C 語言來撰寫 Python 模塊,而且在編譯後,你能夠經過標準 Python 解釋器在你的 Python 代碼中使用它們。

 

模塊是一個包含全部你定義的函數和變量的文件,其後綴名是.py。

 

模塊能夠被別的程序引入,以使用該模塊中的函數等功能。

 

這也是使用 Python 標準庫的方法。

 

當解釋器遇到 import 語句,若是模塊在當前的搜索路徑就會被導入。

 

搜索路徑是一個解釋器會先進行搜索的全部目錄的列表。

 

如想要導入模塊,須要把命令放在腳本的頂端。

 

一個模塊只會被導入一次,這樣能夠防止導入模塊被一遍又一遍地執行。

 

搜索路徑被存儲在 sys 模塊中的 path 變量。

 

當前目錄指的是程序啓動的目錄。

 

導入模塊

 

導入模塊:

import module1[, module2[,... moduleN]]

 

從模塊中導入一個指定的部分到當前命名空間中:

from modname import name1[, name2[, ... nameN]]

 

把一個模塊的全部內容全都導入到當前的命名空間:

from modname import *

 

__name__ 屬性

 

每一個模塊都有一個 __name__ 屬性,當其值是 '__main__' 時,代表該模塊自身在運行,不然是被引入。

 

一個模塊被另外一個程序第一次引入時,其主程序將運行。

 

若是咱們想在模塊被引入時,模塊中的某一程序塊不執行,咱們能夠用 __name__ 屬性來使該程序塊僅在該模塊自身運行時執行。

 

if __name__ == '__main__':
    print('程序自身在運行')
else:
    print('我來自另外一模塊')

 

dir 函數

 

內置的函數 dir() 能夠找到模塊內定義的全部名稱。

 

以一個字符串列表的形式返回。

 

若是沒有給定參數,那麼 dir() 函數會羅列出當前定義的全部名稱。

 

在 Python 中萬物皆對象,int、str、float、list、tuple等內置數據類型其實也是類,也能夠用 dir(int) 查看 int 包含的全部方法,也可使用 help(int) 查看 int 類的幫助信息。

 

 

包是一種管理 Python 模塊命名空間的形式,採用」點模塊名稱」。

 

好比一個模塊的名稱是 A.B, 那麼他表示一個包 A中的子模塊 B 。

 

就好像使用模塊的時候,你不用擔憂不一樣模塊之間的全局變量相互影響同樣,採用點模塊名稱這種形式也不用擔憂不一樣庫之間的模塊重名的狀況。

 

在導入一個包的時候,Python 會根據 sys.path 中的目錄來尋找這個包中包含的子目錄。

 

目錄只有包含一個叫作 __init__.py 的文件纔會被認做是一個包,主要是爲了不一些濫俗的名字(好比叫作 string)不當心的影響搜索路徑中的有效模塊。

 

最簡單的狀況,放一個空的 __init__.py 文件就能夠了。

 

固然這個文件中也能夠包含一些初始化代碼或者爲 __all__ 變量賦值。

 

第三方模塊

 

  • easy_install 和 pip 都是用來下載安裝 Python 一個公共資源庫 PyPI 的相關資源包的,pip 是 easy_install 的改進版,提供更好的提示信息,刪除 package 等功能。

 

     老版本的 python 中只有 easy_install,沒有pip。

 

  • easy_install 打包和發佈 Python 包,pip 是包管理。

     

easy_install 的用法:

 

easy_install 包名

easy_install "包名 == 包的版本號"
  • 安裝一個包

 

easy_install -U "包名 >= 包的版本號"

 

  • 升級一個包

pip 的用法:

 

pip install 包名
pip install 包名 == 包的版本號
pip install —upgrade 包名 >= 包的版本號
pip uninstall 包名
pip list
  • 安裝一個包

  • 升級一個包 (若是不提供version號,升級到最新版本)

  • 刪除一個包

  • 已安裝包列表

 

面向對象

 

類與對象是面向對象編程的兩個主要方面。

 

一個類(Class)可以建立一種新的類型(Type),其中對象(Object)就是類的實例(Instance)。

 

能夠這樣來類比:你能夠擁有類型 int 的變量,也就是說存儲整數的變量是 int 類的實例(對象)。

 

  • 類(Class):用來描述具備相同的屬性和方法的對象的集合。

 

它定義了該集合中每一個對象所共有的屬性和方法。對象是類的實例。

 

  • 方法:類中定義的函數。

 

  • 類變量:類變量在整個實例化的對象中是公用的。

 

類變量定義在類中且在函數體以外。類變量一般不做爲實例變量使用。

 

  • 數據成員:類變量或者實例變量用於處理類及其實例對象的相關的數據。

 

  • 方法重寫:若是從父類繼承的方法不能知足子類的需求,能夠對其進行改寫,這個過程叫方法的覆蓋(override),也稱爲方法的重寫。

 

  • 實例變量:定義在方法中的變量,只做用於當前實例的類。

 

  • 繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。

 

繼承也容許把一個派生類的對象做爲一個基類對象對待。

 

例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬」是一個(is-a)」關係(例圖,Dog是一個Animal)。

 

  • 實例化:建立一個類的實例,類的具體對象。

 

  • 對象:經過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。

 

Python 中的類提供了面向對象編程的全部基本功能:類的繼承機制容許多個基類,派生類能夠覆蓋基類中的任何方法,方法中能夠調用基類中的同名方法。

 

對象能夠包含任意數量和類型的數據。

 

self

 

self 表示的是當前實例,表明當前對象的地址。

 

類由 self.__class__ 表示。

 

self 不是關鍵字,其餘名稱也能夠替代,但 self 是個通用的標準名稱。

 

 

類由 class 關鍵字來建立。

 

 類實例化後,可使用其屬性,實際上,建立一個類以後,能夠經過類名訪問其屬性。

 

對象方法

 

方法由 def 關鍵字定義,與函數不一樣的是:方法必須包含參數 self, 且爲第一個參數,self 表明的是本類的實例。

 

類方法

 

裝飾器 @classmethod 能夠將方法標識爲類方法。

 

類方法的第一個參數必須爲 cls,而再也不是 self。

 

靜態方法

 

裝飾器 @staticmethod 能夠將方法標識爲靜態方法。

 

靜態方法的第一個參數再也不指定,也就不須要 self 或 cls。

 

__init__ 方法

 

__init__ 方法即構造方法,會在類的對象被實例化時先運行,能夠將初始化的操做放置到該方法中。

 

若是重寫了 __init__,實例化子類就不會調用父類已經定義的 __init__。

 

變量

 

類變量(Class Variable)是共享的(Shared)——它們能夠被屬於該類的全部實例訪問。

 

該類變量只擁有一個副本,當任何一個對象對類變量做出改變時,發生的變更將在其它全部實例中都會獲得體現。

 

對象變量(Object variable)由類的每個獨立的對象或實例所擁有。

 

在這種狀況下,每一個對象都擁有屬於它本身的字段的副本。

 

也就是說,它們不會被共享,也不會以任何方式與其它不一樣實例中的相同名稱的字段產生關聯。

 

在 Python 中,變量名相似 __xxx__ 的,也就是以雙下劃線開頭,而且以雙下劃線結尾的,是特殊變量,特殊變量是能夠直接訪問的,不是 private 變量。

 

因此,不能用 __name__、__score__ 這樣的變量名。

 

訪問控制

 

  • 私有屬性

__private_attr:兩個下劃線開頭,聲明該屬性爲私有,不能在類地外部被使用或直接訪問。

 

  • 私有方法

__private_method:兩個下劃線開頭,聲明該方法爲私有方法,只能在類的內部調用,不能在類地外部調用。

 

咱們還認爲約定,一個下劃線開頭的屬性或方法爲受保護的。

 

好比,_protected_attr、_protected_method。

 

繼承

 

類能夠繼承,而且支持繼承多個父類。

 

在定義類時,類名後的括號中指定要繼承的父類,多個父類之間用逗號分隔。

 

子類的實例能夠徹底訪問所繼承全部父類的非私有屬性和方法。

 

如果父類中有相同的方法名,而在子類使用時未指定,Python 從左至右搜索,即方法在子類中未找到時,從左到右查找父類中是否包含方法。

 

方法重寫

 

子類的方法能夠重寫父類的方法。

 

重寫的方法參數不強制要求保持一致,不過合理的設計都應該保持一致。

 

super() 函數能夠調用父類的一個方法,以多繼承問題。

 

類的專有方法:

 

  • __init__: 構造函數,在生成對象時調用

 

  • __del__: 析構函數,釋放對象時使用

 

  • __repr__: 打印,轉換

 

  • __setitem__: 按照索引賦值

 

  • __getitem__: 按照索引獲取值

 

  • __len__: 得到長度

 

  • __cmp__: 比較運算

 

  • __call__: 函數調用

 

  • __add__: 加運算

 

  • __sub__: 減運算

 

  • __mul__: 乘運算

 

  • __div__: 除運算

 

  • __mod__: 求餘運算

 

  • __pow__: 乘方

 

類的專有方法也支持重載。

 

實例

class Person:
    """人員信息"""


    # 姓名(共有屬性)
    name = ''


    # 年齡(共有屬性)
    age = 0


    def __init__(self, name='', age=0):
        self.name = name
        self.age = age
        
    # 重載專有方法: __str__
    def __str__(self):
        return "這裏重載了 __str__ 專有方法, " + str({'name': self.name, 'age': self.age})
    
    def set_age(self, age):
        self.age = age
        
class Account:
    """帳戶信息"""


    # 帳戶餘額(私有屬性)
    __balance = 0


    # 全部帳戶總額
    __total_balance = 0


    # 獲取帳戶餘額
    # self 必須是方法的第一個參數
    def balance(self):
        return self.__balance
        
    # 增長帳戶餘額
    def balance_add(self, cost):
        # self 訪問的是本實例
        self.__balance += cost
        # self.__class__ 能夠訪問類
        self.__class__.__total_balance += cost
        
    # 類方法(用 @classmethod 標識,第一個參數爲 cls)
    @classmethod
    def total_balance(cls):
        return cls.__total_balance
        
    # 靜態方法(用 @staticmethod 標識,不須要類參數或實例參數)
    @staticmethod
    def exchange(a, b):
        return b, a
        
class Teacher(Person, Account):
    """教師"""


    # 班級名稱
    _class_name = ''


    def __init__(self, name):
        # 第一種重載父類__init__()構造方法
        # super(子類,self).__init__(參數1,參數2,....)
        super(Teacher, self).__init__(name)
        
    def get_info(self):
        # 以字典的形式返回我的信息
        return {
            'name': self.name,  # 此處訪問的是父類Person的屬性值
            'age': self.age,
            'class_name': self._class_name,
            'balance': self.balance(),  # 此處調用的是子類重載過的方法
        }
    # 方法重載
    def balance(self):
        # Account.__balance 爲私有屬性,子類沒法訪問,因此父類提供方法進行訪問
        return Account.balance(self) * 1.1


class Student(Person, Account):
    """學生"""


    _teacher_name = ''


    def __init__(self, name, age=18):
        # 第二種重載父類__init__()構造方法
        # 父類名稱.__init__(self,參數1,參數2,...)
        Person.__init__(self, name, age)
        
    def get_info(self):
        # 以字典的形式返回我的信息
        return {
            'name': self.name,  # 此處訪問的是父類Person的屬性值
            'age': self.age,
            'teacher_name': self._teacher_name,
            'balance': self.balance(),
        }
        
# 教師 John
john = Teacher('John')
john.balance_add(20)
john.set_age(36)  # 子類的實例能夠直接調用父類的方法
print("John's info:", john.get_info())

# 學生 Mary
mary = Student('Mary', 18)
mary.balance_add(18)
print("Mary's info:", mary.get_info())

# 學生 Fake
fake = Student('Fake')
fake.balance_add(30)
print("Fake's info", fake.get_info())

# 三種不一樣的方式調用靜態方法
print("john.exchange('a', 'b'):", john.exchange('a', 'b'))
print('Teacher.exchange(1, 2)', Teacher.exchange(1, 2))
print('Account.exchange(10, 20):', Account.exchange(10, 20))

# 類方法、類屬性
print('Account.total_balance():', Account.total_balance())
print('Teacher.total_balance():', Teacher.total_balance())
print('Student.total_balance():', Student.total_balance())

# 重載專有方法
print(fake)

輸出:

John's info: {'name': 'John', 'age': 36, 'class_name': '', 'balance': 22.0}
Mary's info: {'name': 'Mary', 'age': 18, 'teacher_name': '', 'balance': 18}
Fake's info {'name': 'Fake', 'age': 18, 'teacher_name': '', 'balance': 30}
john.exchange('a', 'b'): ('b', 'a')
Teacher.exchange(1, 2) (2, 1)
Account.exchange(10, 20): (20, 10)
Account.total_balance(): 0
Teacher.total_balance(): 20
Student.total_balance(): 48
這裏重載了 __str__ 專有方法, {'name': 'Fake', 'age': 18}

 

錯誤和異常

 

語法錯誤

 

SyntaxError 類表示語法錯誤,當解釋器發現代碼沒法經過語法檢查時會觸發的錯誤。

 

語法錯誤是沒法用 try...except...捕獲的。

>>> print:
  File "<stdin>", line 1
    print:
         ^
SyntaxError: invalid syntax

 

異常

 

即使程序的語法是正確的,在運行它的時候,也有可能發生錯誤。

 

運行時發生的錯誤被稱爲異常。

 

 錯誤信息的前面部分顯示了異常發生的上下文,並以調用棧的形式顯示具體信息。

>>> 1 + '0'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

 

異常處理

 

Python 提供了 try ... except ... 的語法結構來捕獲和處理異常。

 

try 語句執行流程大體以下:

 

 

  • 首先,執行 try 子句(在關鍵字 try 和關鍵字 except 之間的語句)。

 

  • 若是沒有異常發生,忽略 except 子句,try 子句執行後結束。

     

若是在執行 try 子句的過程當中發生了異常,那麼 try 子句餘下的部分將被忽略。

 

若是異常的類型和 except 以後的名稱相符,那麼對應的 except 子句將被執行。

 

最後執行 try 語句以後的代碼。

 

  • 若是一個異常沒有與任何的 except 匹配,那麼這個異常將會傳遞給上層的 try 中。

     

  • 一個 try 語句可能包含多個 except 子句,分別來處理不一樣的特定的異常。

     

  • 最多隻有一個 except 子句會被執行。

     

  • 處理程序將只針對對應的 try 子句中的異常進行處理,而不是其餘的 try 的處理程序中的異常。

     

  • 一個 except 子句能夠同時處理多個異常,這些異常將被放在一個括號裏成爲一個元組。

     

  • 最後一個 except 子句能夠忽略異常的名稱,它將被看成通配符使用。

     

    可使用這種方法打印一個錯誤信息,而後再次把異常拋出。

     

  • try except 語句還有一個可選的 else 子句,若是使用這個子句,那麼必須放在全部的 except 子句以後,這個子句將在 try 子句沒有發生任何異常的時候執行。

     

  • 異常處理並不只僅處理那些直接發生在 try 子句中的異常,並且還能處理子句中調用的函數(甚至間接調用的函數)裏拋出的異常。

     

  • 無論 try 子句裏面有沒有發生異常,finally 子句都會執行。

     

  • 若是一個異常在 try 子句裏(或者在 except 和 else 子句裏)被拋出,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後再次被拋出。

 

拋出異常

 

使用 raise 語句拋出一個指定的異常。

 

raise 惟一的一個參數指定了要被拋出的異常,它必須是一個異常的實例或者是異常的類(也就是 Exception 的子類)。

 

若是你只想知道這是否拋出了一個異常,並不想去處理它,那麼一個簡單的 raise 語句就能夠再次把它拋出。

 

自定義異常

 

能夠經過建立一個新的異常類來擁有本身的異常。

 

異常類繼承自 Exception 類,能夠直接繼承,或者間接繼承。

 

當建立一個模塊有可能拋出多種不一樣的異常時,一種一般的作法是爲這個包創建一個基礎異常類,而後基於這個基礎類爲不一樣的錯誤狀況建立不一樣的子類。

 

大多數的異常的名字都以」Error」結尾,就跟標準的異常命名同樣。

 

實例

import sys
class Error(Exception):
    """Base class for exceptions in this module."""
    pass
# 自定義異常
class InputError(Error):
    """Exception raised for errors in the input.
    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
try:
    print('code start running...')
    raise InputError('input()', 'input error')
    # ValueError
    int('a')
    # TypeError
    s = 1 + 'a'
    dit = {'name': 'john'}
    # KeyError
    print(dit['1'])
except InputError as ex:
    print("InputError:", ex.message)
except TypeError as ex:
    print('TypeError:', ex.args)
    pass
except (KeyError, IndexError) as ex:
    """支持同時處理多個異常, 用括號放到元組裏"""
    print(sys.exc_info())
except:
    """捕獲其餘未指定的異常"""
    print("Unexpected error:", sys.exc_info()[0])
    # raise 用於拋出異常
    raise RuntimeError('RuntimeError')
else:
    """當無任何異常時, 會執行 else 子句"""
    print('"else" 子句...')
finally:
    """不管有無異常, 均會執行 finally"""
    print('finally, ending')

 

文件操做

 

打開文件

 

open() 函數用於打開/建立一個文件,並返回一個 file 對象:

open(filename, mode)
  • filename:包含了你要訪問的文件名稱的字符串值

 

  • mode:決定了打開文件的模式:只讀,寫入,追加等

 

文件打開模式:

 

文件對象方法

 

  • fileObject.close()

close() 方法用於關閉一個已打開的文件。

 

關閉後的文件不能再進行讀寫操做,不然會觸發 ValueError 錯誤。

      

 close() 方法容許調用屢次。 

 

當 file 對象,被引用到操做另一個文件時,Python 會自動關閉以前的 file 對象。 使用 close() 方法關閉文件是一個好的習慣。

 

  • fileObject.flush()

flush() 方法是用來刷新緩衝區的,即將緩衝區中的數據馬上寫入文件,同時清空緩衝區,不須要是被動的等待輸出緩衝區寫入。

 

通常狀況下,文件關閉後會自動刷新緩衝區,但有時你須要在關閉前刷它,這時就可使用 flush() 方法。

 

  • fileObject.fileno()

fileno() 方法返回一個整型的文件描述符(file descriptor FD 整型),可用於底層操做系統的 I/O 操做。

 

  • fileObject.isatty()

isatty() 方法檢測文件是否鏈接到一個終端設備,若是是返回 True,不然返回 False。

 

  • next(iterator[,default])

 Python 3 中的 File 對象不支持 next() 方法。

 

 Python 3 的內置函數 next() 經過迭代器調用 __next__() 方法返回下一          項。

 

在循環中,next() 函數會在每次循環中調用,該方法返回文件的下一行,         若是到達結尾(EOF),則觸發 StopIteration。

 

  • fileObject.read()

    read() 方法用於從文件讀取指定的字節數,若是未給定或爲負則讀取全部。

     

  • fileObject.readline()

readline() 方法用於從文件讀取整行,包括 「\n」 字符。

 

 若是指定了一個非負數的參數,則返回指定大小的字節數,包括 「\n」 字符。

 

  • fileObject.readlines()

readlines() 方法用於讀取全部行(直到結束符 EOF)並返回列表,該列表能夠由 Python 的 for... in ... 結構進行處理。

 

若是碰到結束符 EOF,則返回空字符串。

 

  • fileObject.seek(offset[, whence])

seek() 方法用於移動文件讀取指針到指定位置。

 

whence 的值, 若是是 0 表示開頭, 若是是 1 表示當前位置, 2 表示文件的結尾。

 

whence 值爲默認爲0,即文件開頭。

 

例如:

 

seek(x, 0):從起始位置即文件首行首字符開始移動 x 個字符

 

seek(x, 1):表示從當前位置日後移動 x 個字符

 

seek(-x, 2):表示從文件的結尾往前移動 x 個字符

 

  • fileObject.tell(offset[, whence])

    tell() 方法返回文件的當前位置,即文件指針當前位置。

 

  • fileObject.truncate([size])

truncate() 方法用於從文件的首行首字符開始截斷,截斷文件爲 size 個字符,無 size 表示從當前位置截斷;截斷以後 V 後面的全部字符被刪除,其中 Widnows 系統下的換行表明2個字符大小。

 

  • fileObject.write([str])

write() 方法用於向文件中寫入指定字符串。

 

在文件關閉前或緩衝區刷新前,字符串內容存儲在緩衝區中,這時你在文件中是看不到寫入的內容的。

 

若是文件打開模式帶 b,那寫入文件內容時,str (參數)要用 encode 方法轉爲 bytes 形式,不然報錯:TypeError: a bytes-like object is required, not 'str'。

 

  • fileObject.writelines([str])

writelines() 方法用於向文件中寫入一序列的字符串。

 

這一序列字符串能夠是由迭代對象產生的,如一個字符串列表。換行須要指定換行符 \n。

 

實例

filename = 'data.log'
# 打開文件(a+ 追加讀寫模式)
# 用 with 關鍵字的方式打開文件,會自動關閉文件資源
with open(filename, 'w+', encoding='utf-8') as file:
    print('文件名稱: {}'.format(file.name))
    print('文件編碼: {}'.format(file.encoding))
    print('文件打開模式: {}'.format(file.mode))
    print('文件是否可讀: {}'.format(file.readable()))
    print('文件是否可寫: {}'.format(file.writable()))
    print('此時文件指針位置爲: {}'.format(file.tell()))
    # 寫入內容
    num = file.write("第一行內容\n")
    print('寫入文件 {} 個字符'.format(num))
    # 文件指針在文件尾部,故無內容
    print(file.readline(), file.tell())
    # 改變文件指針到文件頭部
    file.seek(0)
    # 改變文件指針後,讀取到第一行內容
    print(file.readline(), file.tell())
    # 但文件指針的改變,卻不會影響到寫入的位置
    file.write('第二次寫入的內容\n')
    # 文件指針又回到了文件尾
    print(file.readline(), file.tell())
    # file.read() 從當前文件指針位置讀取指定長度的字符
    file.seek(0)
    print(file.read(9))
    # 按行分割文件,返回字符串列表
    file.seek(0)
    print(file.readlines())
    # 迭代文件對象,一行一個元素
    file.seek(0)
    for line in file:
        print(line, end='')
# 關閉文件資源
if not file.closed:
    file.close()

輸出:

文件名稱: data.log
文件編碼: utf-8
文件打開模式: w+
文件是否可讀: True
文件是否可寫: True
此時文件指針位置爲: 0
寫入文件 6 個字符
 16
第一行內容
 16
 41
第一行內容
第二次
['第一行內容\n', '第二次寫入的內容\n']
第一行內容
第二次寫入的內容

 

序列化

 

在 Python 中 pickle 模塊實現對數據的序列化和反序列化。pickle 支持任何數據類型,包括內置數據類型、函數、類、對象等。

 

方法

 

dump

 

將數據對象序列化後寫入文件

pickle.dump(obj, file, protocol=None, fix_imports=True)

必填參數 obj 表示將要封裝的對象。 

 

必填參數 file 表示 obj 要寫入的文件對象,file 必須以二進制可寫模式打開,即wb。

 

 可選參數 protocol 表示告知 pickle 使用的協議,支持的協議有 0,1,2,3,默認的協議是添加在 Python 3 中的協議3。

 

load

 

從文件中讀取內容並反序列化

pickle.load(file, fix_imports=True, encoding='ASCII', errors='strict')

必填參數 file 必須以二進制可讀模式打開,即rb,其餘都爲可選參數。

 

dumps

 

以字節對象形式返回封裝的對象,不須要寫入文件中

pickle.dumps(obj, protocol=None, fix_imports=True)

loads

 

從字節對象中讀取被封裝的對象,並返回。

pickle.loads(bytes_object, fix_imports=True, encoding='ASCII', errors='strict')

 

實例

import pickle
data = [1, 2, 3]
# 序列化數據並以字節對象返回
dumps_obj = pickle.dumps(data)
print('pickle.dumps():', dumps_obj)
# 從字節對象中反序列化數據
loads_data = pickle.loads(dumps_obj)
print('pickle.loads():', loads_data)
filename = 'data.log'
# 序列化數據到文件中
with open(filename, 'wb') as file:
    pickle.dump(data, file)
# 從文件中加載並反序列化
with open(filename, 'rb') as file:
    load_data = pickle.load(file)
    print('pickle.load():', load_data)

 

輸出:

基礎語法

 

運行 Python

 

交互式解釋器

 

在命令行窗口執行python後,進入 Python 的交互式解釋器。

 

exit() 或 Ctrl + D 組合鍵退出交互式解釋器。

 

命令行腳本

 

在命令行窗口執行python script-file.py,以執行 Python 腳本文件。

 

指定解釋器

 

若是在 Python 腳本文件首行輸入#!/usr/bin/env python,那麼能夠在命令行窗口中執行/path/to/script-file.py以執行該腳本文件。

 

注:該方法不支持 Windows 環境。

 

編碼

 

默認狀況下,3.x 源碼文件都是 UTF-8 編碼,字符串都是 Unicode 字符。

 

也能夠手動指定文件編碼:

# -*- coding: utf-8 -*-

 

或者

 

# encoding: utf-8

 

注意: 該行標註必須位於文件第一行。

 

標識符

 

  • 第一個字符必須是英文字母或下劃線 _ 。

 

  • 標識符的其餘的部分由字母、數字和下劃線組成。

 

  • 標識符對大小寫敏感。

 

注:從 3.x 開始,非 ASCII 標識符也是容許的,但不建議。

 

保留字

 

保留字即關鍵字,咱們不能把它們用做任何標識符名稱。

 

Python 的標準庫提供了一個 keyword 模塊,能夠輸出當前版本的全部關鍵字:

>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

 

註釋

 

單行註釋採用#,多行註釋採用'''或"""。

# 這是單行註釋

'''
這是多行註釋

這是多行註釋
'''

"""
這也是多行註釋

這也是多行註釋
"""

 

行與縮進

 

Python 最具特點的就是使用縮進來表示代碼塊,不須要使用大括號 {}。 

 

縮進的空格數是可變的,可是同一個代碼塊的語句必須包含相同的縮進空格數,縮進不一致,會致使運行錯誤。

 

多行語句

 

Python 一般是一行寫完一條語句。

 

但若是語句很長,咱們可使用反斜槓\來實現多行語句。

 

total = item_one + \
     item_two + \
     item_three

 

在 [], {}, 或 () 中的多行語句,不須要使用反斜槓\。

 

空行

 

函數之間或類的方法之間用空行分隔,表示一段新的代碼的開始。

 

類和函數入口之間也用一行空行分隔,以突出函數入口的開始。

 

空行與代碼縮進不一樣,空行並非 Python 語法的一部分。

 

書寫時不插入空行,Python 解釋器運行也不會出錯。

 

可是空行的做用在於分隔兩段不一樣功能或含義的代碼,便於往後代碼的維護或重構。

 

記住:空行也是程序代碼的一部分。

 

等待用戶輸入

 

input函數能夠實現等待並接收命令行中的用戶輸入。

content = input("\n\n請輸入點東西並按 Enter 鍵\n")
print(content)

 

同一行寫多條語句

 

Python 能夠在同一行中使用多條語句,語句之間使用分號;分割。

import sys; x = 'hello world'; sys.stdout.write(x + '\n')

 

多個語句構成代碼組

 

縮進相同的一組語句構成一個代碼塊,咱們稱之代碼組。

 

if、while、defclass這樣的複合語句,首行以關鍵字開始,以冒號:結束,該行以後的一行或多行代碼構成代碼組。

 

咱們將首行及後面的代碼組稱爲一個子句(clause)。

 

print 輸出

 

print 默認輸出是換行的,若是要實現不換行須要在變量末尾加上end=""或別的非換行符字符串:

print('123') # 默認換行
print('123', end = "") # 不換行

 

import 與 from…import

 

在 Python 用 import 或者 from...import 來導入相應的模塊。

 

將整個模塊導入,格式爲:import module_name

 

從某個模塊中導入某個函數,格式爲:from module_name import func1

 

從某個模塊中導入多個函數,格式爲:from module_name import func1, func2, func3

 

將某個模塊中的所有函數導入,格式爲:from module_name import *

 

運算符

 

算術運算符

 

運算符 描述
+
-
*
/
% 取模
**
// 取整除

 

比較運算符

 

運算符 描述
== 等於
!= 不等於
> 大於
< 小於
>= 大於等於
<= 小於等於

 

賦值運算符

 

 

運算符 描述
= 簡單的賦值運算符
+= 加法賦值運算符
-= 減法賦值運算符
*= 乘法賦值運算符
/= 除法賦值運算符
%= 取模賦值運算符
**= 冪賦值運算符
//= 取整除賦值運算符

 

位運算符

 

 

邏輯運算符

 

 

成員運算符

 

 

身份運算符

 

 

運算符優先級

 

 

具備相同優先級的運算符將從左至右的方式依次進行,用小括號()能夠改變運算順序。

 

變量

 

變量在使用前必須先」定義」(即賦予變量一個值),不然會報錯:

>>> name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined

 

數據類型

 

布爾(bool)

 

只有 True 和 False 兩個值,表示真或假。

 

數字(number)

 

整型(int)

 

整數值,可正數亦可複數,無小數。 

 

3.x 整型是沒有限制大小的,能夠看成 Long 類型使用,因此 3.x 沒有 2.x 的 Long 類型。

 

浮點型(float)

 

浮點型由整數部分與小數部分組成。

 

浮點型也可使用科學計數法表示(2.5e2 = 2.5 x 10^2 = 250)

 

複數(complex)

 

複數由實數部分和虛數部分構成,能夠用a + bj,或者complex(a,b)表示。

 

複數的實部 a 和虛部 b 都是浮點型。

 

數字運算

 

  • 不一樣類型的數字混合運算時會將整數轉換爲浮點數

 

  • 在不一樣的機器上浮點運算的結果可能會不同

 

  • 在整數除法中,除法 / 老是返回一個浮點數。

 

      若是隻想獲得整數的結果,丟棄可能的分數部分,可使用運算符 //。

 

  • // 獲得的並不必定是整數類型的數,它與分母分子的數據類型有關係。

 

  • 在交互模式中,最後被輸出的表達式結果被賦值給變量 _,_ 是個只讀變量

 

數學函數

 

:如下函數的使用,需先導入 math 包。

 

 

隨機數函數

 

:如下函數的使用,需先導入 random 包。

 

 

三角函數

 

:如下函數的使用,需先導入 math 包。

 

 

數學常量

 

字符串(string)

 

  • 單引號和雙引號使用徹底相同。

 

  • 使用三引號('''或""")能夠指定一個多行字符串。

 

  • 轉義符(反斜槓\)能夠用來轉義,使用r可讓反斜槓不發生轉義。

 

      如r"this is a line with \n",則\n會顯示,並非換行。

 

  • 按字面意義級聯字符串。

 

      如"this " "is " "string"會被自動轉換爲this is string。

 

  • 字符串能夠用 + 運算符鏈接在一塊兒,用 * 運算符重複。

 

  • 字符串有兩種索引方式,從左往右以 0 開始,從右往左以 -1 開始。

 

  • 字符串不能改變。

 

  • 沒有單獨的字符類型,一個字符就是長度爲 1 的字符串。

 

  • 字符串的截取的語法格式以下:變量[頭下標:尾下標]。

 

轉義字符

 

 

字符串運算符

 

 

字符串格式化

 

在 Python 中,字符串格式化不是 sprintf 函數,而是用 % 符號。

 

例如:

print("我叫%s, 今年 %d 歲!" % ('小明', 10))

// 輸出:
我叫小明, 今年 10 歲!

 

格式化符號:

 

 

輔助指令:

 

 

Python 2.6 開始,新增了一種格式化字符串的函數 str.format(),它加強了字符串格式化的功能。

 

多行字符串

 

  • 用三引號(''' 或 """)包裹字符串內容

 

  • 多行字符串內容支持轉義符,用法與單雙引號同樣

 

  • 三引號包裹的內容,有變量接收或操做即字符串,不然就是多行註釋

 

實例:

string = '''
print(\tmath.fabs(-10))

print(\nrandom.choice(li))
'''


print(string)

 

輸出:

print(  math.fabs(-10))

print(
random.choice(li))

 

Unicode

 

在 2.x 中,普通字符串是以 8 位 ASCII 碼進行存儲的。

 

而 Unicode 字符串則存儲爲 16 位 Unicode 字符串,這樣可以表示更多的字符集。

 

使用的語法是在字符串前面加上前綴 u。

 

在 3.x 中,全部的字符串都是 Unicode 字符串。

 

字符串函數

 

 

字節(bytes)

 

在 3.x 中,字符串和二進制數據徹底區分開。

 

文本老是 Unicode,由 str 類型表示,二進制數據則由 bytes 類型表示。

 

Python 3 不會以任意隱式的方式混用 str 和 bytes,你不能拼接字符串和字節流,也沒法在字節流裏搜索字符串(反之亦然),也不能將字符串傳入參數爲字節流的函數(反之亦然)。

 

  • bytes 類型與 str 類型,兩者的方法僅有 encode() 和 decode() 不一樣。

 

  • bytes 類型數據需在常規的 str 類型前加個 b 以示區分,例如 b'abc'。

 

  • 只有在須要將 str 編碼(encode)成 bytes 的時候。

 

     好比:經過網絡傳輸數據;或者須要將 bytes 解碼(decode)成 str 的時候,      咱們纔會關注 str 和 bytes 的區別。

 

bytes 轉 str:

b'abc'.decode()
str(b'abc')
str(b'abc', encoding='utf-8')

 

str 轉 bytes:

'中國'.encode()
bytes('中國', encoding='utf-8')

 

列表(list)

 

  • 列表是一種無序的、可重複的數據序列,能夠隨時添加、刪除其中的元素。

 

  • 列表頁的每一個元素都分配一個數字索引,從 0 開始。

 

  • 列表使用方括號建立,使用逗號分隔元素。

 

  • 列表元素值能夠是任意類型,包括變量。

 

  • 使用方括號對列表進行元素訪問、切片、修改、刪除等操做,開閉合區間爲[)形式。

 

  • 列表的元素訪問能夠嵌套。

 

  • 方括號內能夠是任意表達式。

 

建立列表

hello = (1, 2, 3)
li = [1, "2", [3, 'a'], (1, 3), hello]

 

訪問元素

li = [1, "2", [3, 'a'], (1, 3)]
print(li[3])        # (1, 3)
print(li[-2])       # [3, 'a']

 

切片訪問

 

格式: list_name[begin:end:step] begin 表示起始位置(默認爲0),end 表示結束位置(默認爲最後一個元素),step 表示步長(默認爲1)。

 

hello = (1, 2, 3)
li = [1, "2", [3, 'a'], (1, 3), hello]

print(li)           # [1, '2', [3, 'a'], (1, 3), (1, 2, 3)]
print(li[1:2])      # ['2']
print(li[:2])       # [1, '2']
print(li[:])        # [1, '2', [3, 'a'], (1, 3), (1, 2, 3)]
print(li[2:])       # [[3, 'a'], (1, 3), (1, 2, 3)]
print(li[1:-1:2])   # ['2', (1, 3)]

 

訪問內嵌 list 的元素:

li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ['a', 'b', 'c']]

print(li[1:-1:2][1:3])      # (3, 5)
print(li[-1][1:3])          # ['b', 'c']
print(li[-1][1])            # b

 

修改列表

 

經過使用方括號,能夠很是靈活的對列表的元素進行修改、替換、刪除等操做。

li = [0, 1, 2, 3, 4, 5]
li[len(li) - 2] = 22    # 修改 [0, 1, 2, 22, 4, 5]
li[3] = 33              # 修改 [0, 1, 2, 33, 4, 5]
li[1:-1] = [9, 9]       # 替換 [0, 9, 9, 5]
li[1:-1] = []           # 刪除 [0, 5]

 

刪除元素

 

能夠用 del 語句來刪除列表的指定範圍的元素。

li = [0, 1, 2, 3, 4, 5]

del li[3]       # [0, 1, 2, 4, 5]
del li[2:-1]    # [0, 1, 5]

 

列表操做符

 

  • + 用於合併列表。

 

  • * 用於重複列表元素。

 

  • in 用於判斷元素是否存在於列表中。

 

  • for ... in ... 用於遍歷列表元素。

 

[1, 2, 3] + [3, 4, 5]           # [1, 2, 3, 3, 4, 5]
[1, 2, 3] * 2                   # [1, 2, 3, 1, 2, 3]
3 in [1, 2, 3]                  # True
for x in [1, 2, 3]: print(x)    # 1 2 3

 

列表函數

 

  • len(list) 列表元素個數

 

  • max(list) 列表元素中的最大值

 

  • min(list) 列表元素中的最小值

 

  • list(seq) 將元組轉換爲列表

 

li = [0, 1, 5]

max(li)     # 5
len(li)     # 3

 

注: 對列表使用 max/min 函數,2.x 中對元素值類型無要求,3.x 則要求元素值類型必須一致。

 

列表方法

 

  • list.append(obj)

在列表末尾添加新的對象

 

  • list.count(obj)

返回元素在列表中出現的次數

 

  • list.extend(seq)

在列表末尾一次性追加另外一個序列中的多個值

 

  • list.index(obj)

返回查找對象的索引位置,若是沒有找到對象則拋出異常

 

  • list.insert(index, obj)

將指定對象插入列表的指定位置

 

  • list.pop([index=-1]])

移除列表中的一個元素(默認最後一個元素),而且返回該元素的值

 

  • list.remove(obj)

移除列表中某個值的第一個匹配項

 

  • list.reverse()

反向排序列表的元素

 

  • list.sort(cmp=None, key=None, reverse=False)

對原列表進行排序,若是指定參數,則使用比較函數指定的比較函數

 

  • list.clear()

清空列表 還可使用 del list[:]、li = [] 等方式實現

 

  • list.copy()

複製列表 默認使用等號賦值給另外一個變量,其實是引用列表變量。若是要實現

 

列表推導式

 

列表推導式提供了從序列建立列表的簡單途徑。

 

一般應用程序將一些操做應用於某個序列的每一個元素,用其得到的結果做爲生成新列表的元素,或者根據肯定的斷定條件建立子序列。

 

每一個列表推導式都在 for 以後跟一個表達式,而後有零到多個 for 或 if 子句。

 

返回結果是一個根據表達從其後的 for 和 if 上下文環境中生成出來的列表。

 

若是但願表達式推導出一個元組,就必須使用括號。

 

將列表中每一個數值乘三,得到一個新的列表:

vec = [2, 4, 6]
[(x, x**2) for x in vec]
# [(2, 4), (4, 16), (6, 36)]

 

對序列裏每個元素逐個調用某方法:

freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
[weapon.strip() for weapon in freshfruit]
# ['banana', 'loganberry', 'passion fruit']

 

用 if 子句做爲過濾器:

vec = [2, 4, 6]
[3*x for x in vec if x > 3]
# [12, 18]
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
[x*y for x in vec1 for y in vec2]
# [8, 6, -18, 16, 12, -36, 24, 18, -54]
[vec1[i]*vec2[i] for i in range(len(vec1))]
# [8, 12, -54]

 

列表嵌套解析:

matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
new_matrix = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(new_matrix)
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

 

元組(tuple)

 

  • 元組與列表相似,不一樣之處在於元組的元素不能修改

 

  • 元組使用小括號,列表使用方括號

 

  • 元組建立很簡單,只須要在括號中添加元素,並使用逗號隔開便可

 

  • 沒有 append(),insert() 這樣進行修改的方法,其餘方法都與列表同樣

 

  • 字典中的鍵必須是惟一的同時不可變的,值則沒有限制

 

  • 元組中只包含一個元素時,須要在元素後面添加逗號,不然括號會被看成運算符使用

 

訪問元組

 

訪問元組的方式與列表是一致的。 

 

元組的元素能夠直接賦值給多個變量,但變量數必須與元素數量一致。

a, b, c = (1, 2, 3)
print(a, b, c)

 

組合元組

 

元組中的元素值是不容許修改的,但咱們能夠對元組進行鏈接組合。

tup1 = (12, 34.56);
tup2 = ('abc', 'xyz')
tup3 = tup1 + tup2;
print (tup3)
# (12, 34.56, 'abc', 'xyz')

 

刪除元組

 

元組中的元素值是不容許刪除的,但咱們可使用 del 語句來刪除整個元組

元組函數

 

  • len(tuple) 元組元素個數

 

  • max(tuple) 元組元素中的最大值

 

  • min(tuple) 元組元素中的最小值

 

  • tuple(tuple) 將列表轉換爲元組

 

元組推導式

t = 1, 2, 3
print(t)
# (1, 2, 3)
u = t, (3, 4, 5)
print(u)
# ((1, 2, 3), (3, 4, 5))

 

字典(dict)

 

  • 字典是另外一種可變容器模型,可存儲任意類型對象

 

  • 字典的每一個鍵值(key=>value)對用冒號(:)分割,每一個對之間用逗號(,)分割,整個字典包括在花括號({})中

 

  • 鍵必須是惟一的,但值則沒必要

 

  • 值能夠是任意數據類型

 

  • 鍵必須是不可變的,例如:數字、字符串、元組能夠,但列表就不行

 

  • 若是用字典裏沒有的鍵訪問數據,會報錯

 

  • 字典的元素沒有順序,不能經過下標引用元素,經過鍵來引用

 

  • 字典內部存放的順序和 key 放入的順序是沒有關係的

 

格式以下:

d = {key1 : value1, key2 : value2 }

 

訪問字典

dis = {'a': 1, 'b': [1, 2, 3]}

print(dis['b'][2])

 

修改字典

dis = {'a': 1, 'b': [1, 2, 3], 9: {'name': 'hello'}}

dis[9]['name'] = 999
print(dis)

# {'a': 1, 9: {'name': 999}, 'b': [1, 2, 3]}

 

刪除字典

 

用 del 語句刪除字典或字典的元素。

dis = {'a': 1, 'b': [1, 2, 3], 9: {'name': 'hello'}}

del dis[9]['name']
print(dis)

del dis         # 刪除字典


# {'a': 1, 9: {}, 'b': [1, 2, 3]}

 

字典函數

 

  • len(dict) 計算字典元素個數,即鍵的總數

 

  • str(dict) 輸出字典,以可打印的字符串表示

 

  • type(variable) 返回輸入的變量類型,若是變量是字典就返回字典類型

 

  • key in dict 判斷鍵是否存在於字典中

 

字典方法

 

  • dict.clear()

刪除字典內全部元素

 

  • dict.copy()

返回一個字典的淺複製

 

  • dict.fromkeys(seq[, value])

建立一個新字典,以序列 seq 中元素作字典的鍵,value 爲字典全部鍵對應的初始值

 

  • dict.get(key, default=None)

返回指定鍵的值,若是值不在字典中返回默認值

 

  • dict.items()

以列表形式返回可遍歷的(鍵, 值)元組數組

 

  • dict.keys()

以列表返回一個字典全部的鍵

 

  • dict.values()

以列表返回字典中的全部值

 

  • dict.setdefault(key, default=None)

若是 key 在字典中,返回對應的值。

 

若是不在字典中,則插入 key 及設置的默認值 default,並返回 default ,default 默認值爲 None。

 

  • dict.update(dict2)

把字典參數 dict2 的鍵/值對更新到字典 dict 裏

dic1 = {'a': 'a'}
dic2 = {9: 9, 'a': 'b'}
dic1.update(dic2)
print(dic1)

# {'a': 'b', 9: 9}

 

  • dict.pop(key[,default])

刪除字典給定鍵 key 所對應的值,返回值爲被刪除的值。key 值必須給出,不然返回 default 值。

 

  • dict.popitem()

隨機返回並刪除字典中的一對鍵和值(通常刪除末尾對)

 

字典推導式

 

構造函數 dict() 直接從鍵值對元組列表中構建字典。若是有固定的模式,列表推導式指定特定的鍵值對:

>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}

 

此外,字典推導能夠用來建立任意鍵和值的表達式詞典:

>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}

 

若是關鍵字只是簡單的字符串,使用關鍵字參數指定鍵值對有時候更方便:

>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

 

集合(set)

 

集合是一個無序不重複元素的序列

 

建立集合

 

  • 可使用大括號 {} 或者 set() 函數建立集合

 

  • 建立一個空集合必須用 set() 而不是 {},由於 {} 是用來建立一個空字典

set(value) 方式建立集合,value 能夠是字符串、列表、元組、字典等序列類型

 

  • 建立、添加、修改等操做,集合會自動去重

{1, 2, 1, 3}            # {} {1, 2, 3}
set('12345')            # 字符串 {'3', '5', '4', '2', '1'}
set([1, 'a', 23.4])     # 列表 {1, 'a', 23.4}
set((1, 'a', 23.4))     # 元組 {1, 'a', 23.4}
set({1:1, 'b': 9})      # 字典 {1, 'b'}

 

添加元素

 

將元素 val 添加到集合 set 中,若是元素已存在,則不進行任何操做:

set.add(val)

 

也能夠用 update 方法批量添加元素,參數能夠是列表,元組,字典等:

set.update(list1, list2,...)

 

移除元素

 

若是存在元素 val 則移除,不存在就報錯:

set.remove(val)

 

若是存在元素 val 則移除,不存在也不會報錯:

set.discard(val)

 

隨機移除一個元素:

set.pop()

 

元素個數

 

與其餘序列同樣,能夠用 len(set) 獲取集合的元素個數。

 

清空集合

 

set.clear()

set = set()

 

判斷元素是否存在

val in set

 

其餘方法

 

  • set.copy()

複製集合

 

  • set.difference(set2)

求差集,在 set 中卻不在 set2 中

 

  • set.intersection(set2)

求交集,同時存在於 set 和 set2 中

 

  • set.union(set2)

求並集,全部 set 和 set2 的元素

 

  • set.symmetric_difference(set2)

求對稱差集,不一樣時出如今兩個集合中的元素

 

  • set.isdisjoint(set2)

若是兩個集合沒有相同的元素,返回 True

 

  • set.issubset(set2)

若是 set 是 set2 的一個子集,返回 True

 

  • set.issuperset(set2)

若是 set 是 set2 的一個超集,返回 True

 

集合計算

a = set('abracadabra')
b = set('alacazam')

print(a)                                  # a 中惟一的字母
# {'a', 'r', 'b', 'c', 'd'}


print(a - b)                              # 在 a 中的字母,但不在 b 中
# {'r', 'd', 'b'}


print(a | b)                              # 在 a 或 b 中的字母
# {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
print(a & b)                              # 在 a 和 b 中都有的字母
# {'a', 'c'}
print(a ^ b)                              # 在 a 或 b 中的字母,但不一樣時在 a 和 b 中
# {'r', 'd', 'b', 'm', 'z', 'l'}

 

集合推導式

a = {x for x in 'abracadabra' if x not in 'abc'}
print(a)
# {'d', 'r'}

 

流程控制

 

if 控制

if 表達式1:
    語句
    if 表達式2:
        語句
    elif 表達式3:
        語句
    else:
        語句
elif 表達式4:
    語句
else:
    語句

 

一、每一個條件後面要使用冒號 :,表示接下來是知足條件後要執行的語句塊。

 

 二、使用縮進來劃分語句塊,相同縮進數的語句在一塊兒組成一個語句塊。 

 

三、在 Python 中沒有 switch - case 語句。

 

三元運算符:

<表達式1> if <條件> else <表達式2>

編寫條件語句時,應該儘可能避免使用嵌套語句。

 

嵌套語句不便於閱讀,並且可能會忽略一些可能性。

 

for 遍歷

for <循環變量> in <循環對象>:
    <語句1>
else:
    <語句2>

 

else 語句中的語句2只有循環正常退出(遍歷完全部遍歷對象中的值)時執行。

 

在字典中遍歷時,關鍵字和對應的值可使用 items() 方法同時解讀出來:

knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)

 

在序列中遍歷時,索引位置和對應值可使用 enumerate() 函數同時獲得:

for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)

 

同時遍歷兩個或更多的序列,可使用 zip() 組合:

questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
    print('What is your {0}?  It is {1}.'.format(q, a))

 

要反向遍歷一個序列,首先指定這個序列,而後調用 reversed() 函數:

for i in reversed(range(1, 10, 2)):
    print(i)

 

要按順序遍歷一個序列,使用 sorted() 函數返回一個已排序的序列,並不修改原值:

basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
    print(f)

 

while 循環

while<條件>:
    <語句1>
else:
    <語句2>

break、continue、pass

 

break 語句用在 while 和 for 循環中,break 語句用來終止循環語句。

 

即循環條件沒有 False 條件或者序列還沒被徹底遞歸完,也會中止執行循環語句。

 

continue 語句用在 while 和 for 循環中,continue 語句用來告訴 Python 跳過當前循環的剩餘語句,而後繼續進行下一輪循環。 

 

continue 語句跳出本次循環,而 break 跳出整個循環。

 

pass 是空語句,是爲了保持程序結構的完整性。

 

pass 不作任何事情,通常用作佔位語句。

 

迭代器

 

  • 迭代器是一個能夠記住遍歷的位置的對象。

 

  • 迭代器對象從集合的第一個元素開始訪問,直到全部的元素被訪問完結束。

 

迭代器只能往前不會後退。

 

  • 迭代器有兩個基本的方法:iter() 和 next()

 

  • 字符串,列表或元組對象均可用於建立迭代器。

 

迭代器能夠被 for 循環進行遍歷:

li = [1, 2, 3]
it = iter(li)
for val in it:
    print(val)

 

迭代器也能夠用 next() 函數訪問下一個元素值:

import sys

li = [1,2,3,4]
it = iter(li)

while True:
    try:
        print (next(it))
    except StopIteration:
        sys.exit()

 

生成器

 

  • 在 Python 中,使用了 yield 的函數被稱爲生成器(generator)。

 

  • 跟普通函數不一樣的是,生成器是一個返回迭代器的函數,只能用於迭代操做。

 

更簡單點理解生成器就是一個迭代器。

 

  • 在調用生成器運行的過程當中,每次遇到 yield 時函數會暫停並保存當前全部的運行信息,返回 yield 的值,並在下一次執行 next() 方法時從當前位置繼續運行。

 

  • 調用一個生成器函數,返回的是一個迭代器對象。

import sys

def fibonacci(n): # 生成器函數 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1


f = fibonacci(10) # f 是一個迭代器,由生成器返回生成

while True:
    try:
        print(next(f))
    except StopIteration:
        sys.exit()

 

函數

 

自定義函數

 

函數(Functions)是指可重複使用的程序片斷。

 

它們容許你爲某個代碼塊賦予名字,容許你經過這一特殊的名字在你的程序任何地方來運行代碼塊,並可重複任何次數。

 

這就是所謂的調用(Calling)函數。

 

  • 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()。

 

  • 任何傳入參數和自變量必須放在圓括號中間,圓括號之間能夠用於定義參數。

 

  • 函數的第一行語句能夠選擇性地使用文檔字符串—用於存放函數說明。

 

  • 函數內容以冒號起始,而且縮進。

 

  • return [表達式] 結束函數,選擇性地返回一個值給調用方。

 

不帶表達式的 return 至關於返回 None。

 

  • return 能夠返回多個值,此時返回的數據未元組類型。

 

  • 定義參數時,帶默認值的參數必須在無默認值參數的後面。

 

def 函數名(參數列表):
    函數體

 

參數傳遞

 

在 Python 中,類型屬於對象,變量是沒有類型的:

a = [1,2,3]

a = "Runoob"

 

以上代碼中,[1,2,3] 是 List 類型,」Runoob」 是 String 類型。

 

而變量 a 是沒有類型,她僅僅是一個對象的引用(一個指針),能夠是指向 List 類型對象,也能夠是指向 String 類型對象。

 

可更改與不可更改對象

 

在 Python 中,字符串,數字和元組是不可更改的對象。

 

而列表、字典等則是能夠修改的對象。

 

  • 不可變類型:變量賦值 a=5 後再賦值 a=10,這裏實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,至關於新生成了a。

 

  • 可變類型:變量賦值 la=[1,2,3,4] 後再賦值 la[2]=5 ,則是將 list la 的第三個元素值更改,自己la沒有動,只是其內部的一部分值被修改了。

 

Python 函數的參數傳遞:

 

  • 不可變類型:相似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象自己。

 

好比在 fun(a)內部修改 a 的值,只是修改另外一個複製的對象,不會影響 a 自己。

 

  • 可變類型:相似 c++ 的引用傳遞,如 列表,字典。

 

如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響

 

Python 中一切都是對象,嚴格意義咱們不能說值傳遞仍是引用傳遞,咱們應該說傳不可變對象和傳可變對象。

 

參數

 

必需參數

 

必需參數須以正確的順序傳入函數。

 

調用時的數量必須和聲明時的同樣。

 

關鍵字參數

 

關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來肯定傳入的參數值。 

 

使用關鍵字參數容許函數調用時參數的順序與聲明時不一致,由於 Python 解釋器可以用參數名匹配參數值。

 

def print_info(name, age):
    "打印任何傳入的字符串"
    print("名字: ", name)
    print("年齡: ", age)
    return
print_info(age=50, name="john")

 

默認參數

 

調用函數時,若是沒有傳遞參數,則會使用默認參數。

 

def print_info(name, age=35):
    print ("名字: ", name)
    print ("年齡: ", age)
    return


print_info(age=50, name="john")
print("------------------------")
print_info(name="john")

 

不定長參數

 

  • 加了星號 * 的參數會以元組的形式導入,存放全部未命名的變量參數。

 

  • 若是在函數調用時沒有指定參數,它就是一個空元組。

 

咱們也能夠不向函數傳遞未命名的變量。

 

def print_info(arg1, *vartuple):
    print("輸出: ")
    print(arg1)
    for var in vartuple:
        print (var)
    return
print_info(10)
print_info(70, 60, 50)

 

  • 加了兩個星號 ** 的參數會以字典的形式導入,變量名爲鍵,變量值爲字典元素值。

 

def print_info(arg1, **vardict):
    print("輸出: ")
    print(arg1)
    print(vardict)
print_info(1, a=2, b=3)

 

匿名函數

 

Python 使用 lambda 來建立匿名函數。

 

所謂匿名,意即再也不使用 def 語句這樣標準的形式定義一個函數。

 

lambda 只是一個表達式,函數體比 def 簡單不少。

 

 lambda 的主體是一個表達式,而不是一個代碼塊。

 

僅僅能在 lambda 表達式中封裝有限的邏輯進去。 

 

lambda 函數擁有本身的命名空間,且不能訪問本身參數列表以外或全局命名空間裏的參數。 

 

雖然 lambda 函數看起來只能寫一行,卻不等同於 C 或 C++ 的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增長運行效率。

 

# 語法格式
lambda [arg1 [,arg2,.....argn]]:expression

 

變量做用域

 

  • L (Local) 局部做用域

 

  • E (Enclosing) 閉包函數外的函數中

 

  • G (Global) 全局做用域

 

  • B (Built-in) 內建做用域

 

以 L –> E –> G –> B 的規則查找,即:在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內建中找。

 

Python 中只有模塊(module),類(class)以及函數(def、lambda)纔會引入新的做用域,其它的代碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的做用域的。

 

也就是說這些語句內定義的變量,外部也能夠訪問。

 

定義在函數內部的變量擁有一個局部做用域,定義在函數外的擁有全局做用域。

 

局部變量只能在其被聲明的函數內部訪問,而全局變量能夠在整個程序範圍內訪問。

 

調用函數時,全部在函數內聲明的變量名稱都將被加入到做用域中。

 

當內部做用域想修改外部做用域的變量時,就要用到global和nonlocal關鍵字。

 

num = 1
def fun1():
    global num  # 須要使用 global 關鍵字聲明
    print(num) 
    num = 123
    print(num)
fun1()

 

若是要修改嵌套做用域(enclosing 做用域,外層非全局做用域)中的變量則須要 nonlocal 關鍵字。

 

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal關鍵字聲明
        num = 100
        print(num)
    inner()
    print(num)
outer()

 

模塊

 

編寫模塊有不少種方法。

 

其中最簡單的一種即是建立一個包含函數與變量、以 .py 爲後綴的文件。

 

另外一種方法是使用撰寫 Python 解釋器自己的本地語言來編寫模塊。

 

舉例來講,你可使用 C 語言來撰寫 Python 模塊,而且在編譯後,你能夠經過標準 Python 解釋器在你的 Python 代碼中使用它們。

 

模塊是一個包含全部你定義的函數和變量的文件,其後綴名是.py。

 

模塊能夠被別的程序引入,以使用該模塊中的函數等功能。

 

這也是使用 Python 標準庫的方法。

 

當解釋器遇到 import 語句,若是模塊在當前的搜索路徑就會被導入。

 

搜索路徑是一個解釋器會先進行搜索的全部目錄的列表。

 

如想要導入模塊,須要把命令放在腳本的頂端。

 

一個模塊只會被導入一次,這樣能夠防止導入模塊被一遍又一遍地執行。

 

搜索路徑被存儲在 sys 模塊中的 path 變量。

 

當前目錄指的是程序啓動的目錄。

 

導入模塊

 

導入模塊:

import module1[, module2[,... moduleN]]

 

從模塊中導入一個指定的部分到當前命名空間中:

from modname import name1[, name2[, ... nameN]]

 

把一個模塊的全部內容全都導入到當前的命名空間:

from modname import *

 

__name__ 屬性

 

每一個模塊都有一個 __name__ 屬性,當其值是 '__main__' 時,代表該模塊自身在運行,不然是被引入。

 

一個模塊被另外一個程序第一次引入時,其主程序將運行。

 

若是咱們想在模塊被引入時,模塊中的某一程序塊不執行,咱們能夠用 __name__ 屬性來使該程序塊僅在該模塊自身運行時執行。

 

if __name__ == '__main__':
    print('程序自身在運行')
else:
    print('我來自另外一模塊')

 

dir 函數

 

內置的函數 dir() 能夠找到模塊內定義的全部名稱。

 

以一個字符串列表的形式返回。

 

若是沒有給定參數,那麼 dir() 函數會羅列出當前定義的全部名稱。

 

在 Python 中萬物皆對象,int、str、float、list、tuple等內置數據類型其實也是類,也能夠用 dir(int) 查看 int 包含的全部方法,也可使用 help(int) 查看 int 類的幫助信息。

 

 

包是一種管理 Python 模塊命名空間的形式,採用」點模塊名稱」。

 

好比一個模塊的名稱是 A.B, 那麼他表示一個包 A中的子模塊 B 。

 

就好像使用模塊的時候,你不用擔憂不一樣模塊之間的全局變量相互影響同樣,採用點模塊名稱這種形式也不用擔憂不一樣庫之間的模塊重名的狀況。

 

在導入一個包的時候,Python 會根據 sys.path 中的目錄來尋找這個包中包含的子目錄。

 

目錄只有包含一個叫作 __init__.py 的文件纔會被認做是一個包,主要是爲了不一些濫俗的名字(好比叫作 string)不當心的影響搜索路徑中的有效模塊。

 

最簡單的狀況,放一個空的 __init__.py 文件就能夠了。

 

固然這個文件中也能夠包含一些初始化代碼或者爲 __all__ 變量賦值。

 

第三方模塊

 

  • easy_install 和 pip 都是用來下載安裝 Python 一個公共資源庫 PyPI 的相關資源包的,pip 是 easy_install 的改進版,提供更好的提示信息,刪除 package 等功能。

 

     老版本的 python 中只有 easy_install,沒有pip。

 

  • easy_install 打包和發佈 Python 包,pip 是包管理。

     

easy_install 的用法:

 

easy_install 包名

easy_install "包名 == 包的版本號"
  • 安裝一個包

 

easy_install -U "包名 >= 包的版本號"

 

  • 升級一個包

pip 的用法:

 

pip install 包名
pip install 包名 == 包的版本號
pip install —upgrade 包名 >= 包的版本號
pip uninstall 包名
pip list
  • 安裝一個包

  • 升級一個包 (若是不提供version號,升級到最新版本)

  • 刪除一個包

  • 已安裝包列表

 

面向對象

 

類與對象是面向對象編程的兩個主要方面。

 

一個類(Class)可以建立一種新的類型(Type),其中對象(Object)就是類的實例(Instance)。

 

能夠這樣來類比:你能夠擁有類型 int 的變量,也就是說存儲整數的變量是 int 類的實例(對象)。

 

  • 類(Class):用來描述具備相同的屬性和方法的對象的集合。

 

它定義了該集合中每一個對象所共有的屬性和方法。對象是類的實例。

 

  • 方法:類中定義的函數。

 

  • 類變量:類變量在整個實例化的對象中是公用的。

 

類變量定義在類中且在函數體以外。類變量一般不做爲實例變量使用。

 

  • 數據成員:類變量或者實例變量用於處理類及其實例對象的相關的數據。

 

  • 方法重寫:若是從父類繼承的方法不能知足子類的需求,能夠對其進行改寫,這個過程叫方法的覆蓋(override),也稱爲方法的重寫。

 

  • 實例變量:定義在方法中的變量,只做用於當前實例的類。

 

  • 繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。

 

繼承也容許把一個派生類的對象做爲一個基類對象對待。

 

例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬」是一個(is-a)」關係(例圖,Dog是一個Animal)。

 

  • 實例化:建立一個類的實例,類的具體對象。

 

  • 對象:經過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。

 

Python 中的類提供了面向對象編程的全部基本功能:類的繼承機制容許多個基類,派生類能夠覆蓋基類中的任何方法,方法中能夠調用基類中的同名方法。

 

對象能夠包含任意數量和類型的數據。

 

self

 

self 表示的是當前實例,表明當前對象的地址。

 

類由 self.__class__ 表示。

 

self 不是關鍵字,其餘名稱也能夠替代,但 self 是個通用的標準名稱。

 

 

類由 class 關鍵字來建立。

 

 類實例化後,可使用其屬性,實際上,建立一個類以後,能夠經過類名訪問其屬性。

 

對象方法

 

方法由 def 關鍵字定義,與函數不一樣的是:方法必須包含參數 self, 且爲第一個參數,self 表明的是本類的實例。

 

類方法

 

裝飾器 @classmethod 能夠將方法標識爲類方法。

 

類方法的第一個參數必須爲 cls,而再也不是 self。

 

靜態方法

 

裝飾器 @staticmethod 能夠將方法標識爲靜態方法。

 

靜態方法的第一個參數再也不指定,也就不須要 self 或 cls。

 

__init__ 方法

 

__init__ 方法即構造方法,會在類的對象被實例化時先運行,能夠將初始化的操做放置到該方法中。

 

若是重寫了 __init__,實例化子類就不會調用父類已經定義的 __init__。

 

變量

 

類變量(Class Variable)是共享的(Shared)——它們能夠被屬於該類的全部實例訪問。

 

該類變量只擁有一個副本,當任何一個對象對類變量做出改變時,發生的變更將在其它全部實例中都會獲得體現。

 

對象變量(Object variable)由類的每個獨立的對象或實例所擁有。

 

在這種狀況下,每一個對象都擁有屬於它本身的字段的副本。

 

也就是說,它們不會被共享,也不會以任何方式與其它不一樣實例中的相同名稱的字段產生關聯。

 

在 Python 中,變量名相似 __xxx__ 的,也就是以雙下劃線開頭,而且以雙下劃線結尾的,是特殊變量,特殊變量是能夠直接訪問的,不是 private 變量。

 

因此,不能用 __name__、__score__ 這樣的變量名。

 

訪問控制

 

  • 私有屬性

__private_attr:兩個下劃線開頭,聲明該屬性爲私有,不能在類地外部被使用或直接訪問。

 

  • 私有方法

__private_method:兩個下劃線開頭,聲明該方法爲私有方法,只能在類的內部調用,不能在類地外部調用。

 

咱們還認爲約定,一個下劃線開頭的屬性或方法爲受保護的。

 

好比,_protected_attr、_protected_method。

 

繼承

 

類能夠繼承,而且支持繼承多個父類。

 

在定義類時,類名後的括號中指定要繼承的父類,多個父類之間用逗號分隔。

 

子類的實例能夠徹底訪問所繼承全部父類的非私有屬性和方法。

 

如果父類中有相同的方法名,而在子類使用時未指定,Python 從左至右搜索,即方法在子類中未找到時,從左到右查找父類中是否包含方法。

 

方法重寫

 

子類的方法能夠重寫父類的方法。

 

重寫的方法參數不強制要求保持一致,不過合理的設計都應該保持一致。

 

super() 函數能夠調用父類的一個方法,以多繼承問題。

 

類的專有方法:

 

  • __init__: 構造函數,在生成對象時調用

 

  • __del__: 析構函數,釋放對象時使用

 

  • __repr__: 打印,轉換

 

  • __setitem__: 按照索引賦值

 

  • __getitem__: 按照索引獲取值

 

  • __len__: 得到長度

 

  • __cmp__: 比較運算

 

  • __call__: 函數調用

 

  • __add__: 加運算

 

  • __sub__: 減運算

 

  • __mul__: 乘運算

 

  • __div__: 除運算

 

  • __mod__: 求餘運算

 

  • __pow__: 乘方

 

類的專有方法也支持重載。

 

實例

class Person:
    """人員信息"""


    # 姓名(共有屬性)
    name = ''


    # 年齡(共有屬性)
    age = 0


    def __init__(self, name='', age=0):
        self.name = name
        self.age = age
        
    # 重載專有方法: __str__
    def __str__(self):
        return "這裏重載了 __str__ 專有方法, " + str({'name': self.name, 'age': self.age})
    
    def set_age(self, age):
        self.age = age
        
class Account:
    """帳戶信息"""


    # 帳戶餘額(私有屬性)
    __balance = 0


    # 全部帳戶總額
    __total_balance = 0


    # 獲取帳戶餘額
    # self 必須是方法的第一個參數
    def balance(self):
        return self.__balance
        
    # 增長帳戶餘額
    def balance_add(self, cost):
        # self 訪問的是本實例
        self.__balance += cost
        # self.__class__ 能夠訪問類
        self.__class__.__total_balance += cost
        
    # 類方法(用 @classmethod 標識,第一個參數爲 cls)
    @classmethod
    def total_balance(cls):
        return cls.__total_balance
        
    # 靜態方法(用 @staticmethod 標識,不須要類參數或實例參數)
    @staticmethod
    def exchange(a, b):
        return b, a
        
class Teacher(Person, Account):
    """教師"""


    # 班級名稱
    _class_name = ''


    def __init__(self, name):
        # 第一種重載父類__init__()構造方法
        # super(子類,self).__init__(參數1,參數2,....)
        super(Teacher, self).__init__(name)
        
    def get_info(self):
        # 以字典的形式返回我的信息
        return {
            'name': self.name,  # 此處訪問的是父類Person的屬性值
            'age': self.age,
            'class_name': self._class_name,
            'balance': self.balance(),  # 此處調用的是子類重載過的方法
        }
    # 方法重載
    def balance(self):
        # Account.__balance 爲私有屬性,子類沒法訪問,因此父類提供方法進行訪問
        return Account.balance(self) * 1.1


class Student(Person, Account):
    """學生"""


    _teacher_name = ''


    def __init__(self, name, age=18):
        # 第二種重載父類__init__()構造方法
        # 父類名稱.__init__(self,參數1,參數2,...)
        Person.__init__(self, name, age)
        
    def get_info(self):
        # 以字典的形式返回我的信息
        return {
            'name': self.name,  # 此處訪問的是父類Person的屬性值
            'age': self.age,
            'teacher_name': self._teacher_name,
            'balance': self.balance(),
        }
        
# 教師 John
john = Teacher('John')
john.balance_add(20)
john.set_age(36)  # 子類的實例能夠直接調用父類的方法
print("John's info:", john.get_info())

# 學生 Mary
mary = Student('Mary', 18)
mary.balance_add(18)
print("Mary's info:", mary.get_info())

# 學生 Fake
fake = Student('Fake')
fake.balance_add(30)
print("Fake's info", fake.get_info())

# 三種不一樣的方式調用靜態方法
print("john.exchange('a', 'b'):", john.exchange('a', 'b'))
print('Teacher.exchange(1, 2)', Teacher.exchange(1, 2))
print('Account.exchange(10, 20):', Account.exchange(10, 20))

# 類方法、類屬性
print('Account.total_balance():', Account.total_balance())
print('Teacher.total_balance():', Teacher.total_balance())
print('Student.total_balance():', Student.total_balance())

# 重載專有方法
print(fake)

輸出:

John's info: {'name': 'John', 'age': 36, 'class_name': '', 'balance': 22.0}
Mary's info: {'name': 'Mary', 'age': 18, 'teacher_name': '', 'balance': 18}
Fake's info {'name': 'Fake', 'age': 18, 'teacher_name': '', 'balance': 30}
john.exchange('a', 'b'): ('b', 'a')
Teacher.exchange(1, 2) (2, 1)
Account.exchange(10, 20): (20, 10)
Account.total_balance(): 0
Teacher.total_balance(): 20
Student.total_balance(): 48
這裏重載了 __str__ 專有方法, {'name': 'Fake', 'age': 18}

 

錯誤和異常

 

語法錯誤

 

SyntaxError 類表示語法錯誤,當解釋器發現代碼沒法經過語法檢查時會觸發的錯誤。

 

語法錯誤是沒法用 try...except...捕獲的。

>>> print:
  File "<stdin>", line 1
    print:
         ^
SyntaxError: invalid syntax

 

異常

 

即使程序的語法是正確的,在運行它的時候,也有可能發生錯誤。

 

運行時發生的錯誤被稱爲異常。

 

 錯誤信息的前面部分顯示了異常發生的上下文,並以調用棧的形式顯示具體信息。

>>> 1 + '0'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

 

異常處理

 

Python 提供了 try ... except ... 的語法結構來捕獲和處理異常。

 

try 語句執行流程大體以下:

 

 

  • 首先,執行 try 子句(在關鍵字 try 和關鍵字 except 之間的語句)。

 

  • 若是沒有異常發生,忽略 except 子句,try 子句執行後結束。

     

若是在執行 try 子句的過程當中發生了異常,那麼 try 子句餘下的部分將被忽略。

 

若是異常的類型和 except 以後的名稱相符,那麼對應的 except 子句將被執行。

 

最後執行 try 語句以後的代碼。

 

  • 若是一個異常沒有與任何的 except 匹配,那麼這個異常將會傳遞給上層的 try 中。

     

  • 一個 try 語句可能包含多個 except 子句,分別來處理不一樣的特定的異常。

     

  • 最多隻有一個 except 子句會被執行。

     

  • 處理程序將只針對對應的 try 子句中的異常進行處理,而不是其餘的 try 的處理程序中的異常。

     

  • 一個 except 子句能夠同時處理多個異常,這些異常將被放在一個括號裏成爲一個元組。

     

  • 最後一個 except 子句能夠忽略異常的名稱,它將被看成通配符使用。

     

    可使用這種方法打印一個錯誤信息,而後再次把異常拋出。

     

  • try except 語句還有一個可選的 else 子句,若是使用這個子句,那麼必須放在全部的 except 子句以後,這個子句將在 try 子句沒有發生任何異常的時候執行。

     

  • 異常處理並不只僅處理那些直接發生在 try 子句中的異常,並且還能處理子句中調用的函數(甚至間接調用的函數)裏拋出的異常。

     

  • 無論 try 子句裏面有沒有發生異常,finally 子句都會執行。

     

  • 若是一個異常在 try 子句裏(或者在 except 和 else 子句裏)被拋出,而又沒有任何的 except 把它截住,那麼這個異常會在 finally 子句執行後再次被拋出。

 

拋出異常

 

使用 raise 語句拋出一個指定的異常。

 

raise 惟一的一個參數指定了要被拋出的異常,它必須是一個異常的實例或者是異常的類(也就是 Exception 的子類)。

 

若是你只想知道這是否拋出了一個異常,並不想去處理它,那麼一個簡單的 raise 語句就能夠再次把它拋出。

 

自定義異常

 

能夠經過建立一個新的異常類來擁有本身的異常。

 

異常類繼承自 Exception 類,能夠直接繼承,或者間接繼承。

 

當建立一個模塊有可能拋出多種不一樣的異常時,一種一般的作法是爲這個包創建一個基礎異常類,而後基於這個基礎類爲不一樣的錯誤狀況建立不一樣的子類。

 

大多數的異常的名字都以」Error」結尾,就跟標準的異常命名同樣。

 

實例

import sys
class Error(Exception):
    """Base class for exceptions in this module."""
    pass
# 自定義異常
class InputError(Error):
    """Exception raised for errors in the input.
    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
try:
    print('code start running...')
    raise InputError('input()', 'input error')
    # ValueError
    int('a')
    # TypeError
    s = 1 + 'a'
    dit = {'name': 'john'}
    # KeyError
    print(dit['1'])
except InputError as ex:
    print("InputError:", ex.message)
except TypeError as ex:
    print('TypeError:', ex.args)
    pass
except (KeyError, IndexError) as ex:
    """支持同時處理多個異常, 用括號放到元組裏"""
    print(sys.exc_info())
except:
    """捕獲其餘未指定的異常"""
    print("Unexpected error:", sys.exc_info()[0])
    # raise 用於拋出異常
    raise RuntimeError('RuntimeError')
else:
    """當無任何異常時, 會執行 else 子句"""
    print('"else" 子句...')
finally:
    """不管有無異常, 均會執行 finally"""
    print('finally, ending')

 

文件操做

 

打開文件

 

open() 函數用於打開/建立一個文件,並返回一個 file 對象:

open(filename, mode)
  • filename:包含了你要訪問的文件名稱的字符串值

 

  • mode:決定了打開文件的模式:只讀,寫入,追加等

 

文件打開模式:

 

文件對象方法

 

  • fileObject.close()

close() 方法用於關閉一個已打開的文件。

 

關閉後的文件不能再進行讀寫操做,不然會觸發 ValueError 錯誤。

      

 close() 方法容許調用屢次。 

 

當 file 對象,被引用到操做另一個文件時,Python 會自動關閉以前的 file 對象。 使用 close() 方法關閉文件是一個好的習慣。

 

  • fileObject.flush()

flush() 方法是用來刷新緩衝區的,即將緩衝區中的數據馬上寫入文件,同時清空緩衝區,不須要是被動的等待輸出緩衝區寫入。

 

通常狀況下,文件關閉後會自動刷新緩衝區,但有時你須要在關閉前刷它,這時就可使用 flush() 方法。

 

  • fileObject.fileno()

fileno() 方法返回一個整型的文件描述符(file descriptor FD 整型),可用於底層操做系統的 I/O 操做。

 

  • fileObject.isatty()

isatty() 方法檢測文件是否鏈接到一個終端設備,若是是返回 True,不然返回 False。

 

  • next(iterator[,default])

 Python 3 中的 File 對象不支持 next() 方法。

 

 Python 3 的內置函數 next() 經過迭代器調用 __next__() 方法返回下一          項。

 

在循環中,next() 函數會在每次循環中調用,該方法返回文件的下一行,         若是到達結尾(EOF),則觸發 StopIteration。

 

  • fileObject.read()

    read() 方法用於從文件讀取指定的字節數,若是未給定或爲負則讀取全部。

     

  • fileObject.readline()

readline() 方法用於從文件讀取整行,包括 「\n」 字符。

 

 若是指定了一個非負數的參數,則返回指定大小的字節數,包括 「\n」 字符。

 

  • fileObject.readlines()

readlines() 方法用於讀取全部行(直到結束符 EOF)並返回列表,該列表能夠由 Python 的 for... in ... 結構進行處理。

 

若是碰到結束符 EOF,則返回空字符串。

 

  • fileObject.seek(offset[, whence])

seek() 方法用於移動文件讀取指針到指定位置。

 

whence 的值, 若是是 0 表示開頭, 若是是 1 表示當前位置, 2 表示文件的結尾。

 

whence 值爲默認爲0,即文件開頭。

 

例如:

 

seek(x, 0):從起始位置即文件首行首字符開始移動 x 個字符

 

seek(x, 1):表示從當前位置日後移動 x 個字符

 

seek(-x, 2):表示從文件的結尾往前移動 x 個字符

 

  • fileObject.tell(offset[, whence])

    tell() 方法返回文件的當前位置,即文件指針當前位置。

 

  • fileObject.truncate([size])

truncate() 方法用於從文件的首行首字符開始截斷,截斷文件爲 size 個字符,無 size 表示從當前位置截斷;截斷以後 V 後面的全部字符被刪除,其中 Widnows 系統下的換行表明2個字符大小。

 

  • fileObject.write([str])

write() 方法用於向文件中寫入指定字符串。

 

在文件關閉前或緩衝區刷新前,字符串內容存儲在緩衝區中,這時你在文件中是看不到寫入的內容的。

 

若是文件打開模式帶 b,那寫入文件內容時,str (參數)要用 encode 方法轉爲 bytes 形式,不然報錯:TypeError: a bytes-like object is required, not 'str'。

 

  • fileObject.writelines([str])

writelines() 方法用於向文件中寫入一序列的字符串。

 

這一序列字符串能夠是由迭代對象產生的,如一個字符串列表。換行須要指定換行符 \n。

 

實例

filename = 'data.log'
# 打開文件(a+ 追加讀寫模式)
# 用 with 關鍵字的方式打開文件,會自動關閉文件資源
with open(filename, 'w+', encoding='utf-8') as file:
    print('文件名稱: {}'.format(file.name))
    print('文件編碼: {}'.format(file.encoding))
    print('文件打開模式: {}'.format(file.mode))
    print('文件是否可讀: {}'.format(file.readable()))
    print('文件是否可寫: {}'.format(file.writable()))
    print('此時文件指針位置爲: {}'.format(file.tell()))
    # 寫入內容
    num = file.write("第一行內容\n")
    print('寫入文件 {} 個字符'.format(num))
    # 文件指針在文件尾部,故無內容
    print(file.readline(), file.tell())
    # 改變文件指針到文件頭部
    file.seek(0)
    # 改變文件指針後,讀取到第一行內容
    print(file.readline(), file.tell())
    # 但文件指針的改變,卻不會影響到寫入的位置
    file.write('第二次寫入的內容\n')
    # 文件指針又回到了文件尾
    print(file.readline(), file.tell())
    # file.read() 從當前文件指針位置讀取指定長度的字符
    file.seek(0)
    print(file.read(9))
    # 按行分割文件,返回字符串列表
    file.seek(0)
    print(file.readlines())
    # 迭代文件對象,一行一個元素
    file.seek(0)
    for line in file:
        print(line, end='')
# 關閉文件資源
if not file.closed:
    file.close()

輸出:

文件名稱: data.log
文件編碼: utf-8
文件打開模式: w+
文件是否可讀: True
文件是否可寫: True
此時文件指針位置爲: 0
寫入文件 6 個字符
 16
第一行內容
 16
 41
第一行內容
第二次
['第一行內容\n', '第二次寫入的內容\n']
第一行內容
第二次寫入的內容

 

序列化

 

在 Python 中 pickle 模塊實現對數據的序列化和反序列化。pickle 支持任何數據類型,包括內置數據類型、函數、類、對象等。

 

方法

 

dump

 

將數據對象序列化後寫入文件

pickle.dump(obj, file, protocol=None, fix_imports=True)

必填參數 obj 表示將要封裝的對象。 

 

必填參數 file 表示 obj 要寫入的文件對象,file 必須以二進制可寫模式打開,即wb。

 

 可選參數 protocol 表示告知 pickle 使用的協議,支持的協議有 0,1,2,3,默認的協議是添加在 Python 3 中的協議3。

 

load

 

從文件中讀取內容並反序列化

pickle.load(file, fix_imports=True, encoding='ASCII', errors='strict')

必填參數 file 必須以二進制可讀模式打開,即rb,其餘都爲可選參數。

 

dumps

 

以字節對象形式返回封裝的對象,不須要寫入文件中

pickle.dumps(obj, protocol=None, fix_imports=True)

loads

 

從字節對象中讀取被封裝的對象,並返回。

pickle.loads(bytes_object, fix_imports=True, encoding='ASCII', errors='strict')

 

實例

import pickle
data = [1, 2, 3]
# 序列化數據並以字節對象返回
dumps_obj = pickle.dumps(data)
print('pickle.dumps():', dumps_obj)
# 從字節對象中反序列化數據
loads_data = pickle.loads(dumps_obj)
print('pickle.loads():', loads_data)
filename = 'data.log'
# 序列化數據到文件中
with open(filename, 'wb') as file:
    pickle.dump(data, file)
# 從文件中加載並反序列化
with open(filename, 'rb') as file:
    load_data = pickle.load(file)
    print('pickle.load():', load_data)

 

輸出:

pickle.dumps(): b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
pickle.loads(): [1, 2, 3]
pickle.load(): [1, 2, 3]

 

命名規範

 

Python 之父 Guido 推薦的規範

 

 

命名規範

 

Python 之父 Guido 推薦的規範

 

相關文章
相關標籤/搜索