廖雪峰Python教程筆記(一)
感謝廖老師精彩的Python教程,收益良多,感謝感謝!
整理筆記,以備後續複習,第一部分一直到模組結束,整理如下,其中大量的單引號是有問題的,由於word直接打的,嫌麻煩,沒有都進行修正,請見諒
1、a = ‘XYZ’ 的過程是先在記憶體中建立一個’XYZ’字串,然後建立一個名為a的變數,並指向’XYZ’
2、布林值:True 和 False ,注意大小寫
3、空值:None
4、變數本身型別不固定稱為動態語言
5、常量 就是不能變的變數,python中通常用全部大寫表示名字表示一個常量,但是其本身任然是個變數,你想改也沒人攔得住
6、除分兩種,/ 這種得到的結果是浮點數 // 地板除,類似於取整 %求餘
7、輸出,print(‘AB’, ‘LOVE’, ‘CD’) 輸出結果是AB LOVE CD
8、輸入 name = input()
9、每一行都是一個語句,語句以:結尾的是一個語句塊
10、始終堅持四個空格
11、python大小寫敏感
12、用print(r‘\t’) 這樣可以不用轉義字元了,不然需要轉義
13、用’’’ 可以標識輸出多行 print(‘’’ line1
Line2’’’)
14、字元編碼,最開始英文的時候ascii(一個位元組), 中文GB2312, 所有的 (各國語言)unicode(一般是兩個位元組表示一個字),然後節約精神導致了utf-8:可變長編碼,英文1個位元組,中文一般三個位元組,很生僻的4-6(主要如果是全英文的話,用unicode太浪費了)
所以,當傳輸的文字中有大量的英文字元,那就用utf-8
15、記憶體中都是unicode的編碼方式,當儲存磁碟或者傳輸時,轉成uft-8
16、如從記事本中讀入記憶體又寫回,是先從文字讀取utf-8,轉成unicode到記憶體,編輯完成後,儲存的時候,又轉成uft-8
17、python3裡面都是unicode的 ord()獲取字元整數表示,chr()編碼轉換成對應字串
\u4e2d表示的是unicode的編碼形式,ord()後得到的值就是unicode對應的值的十進位制表示
18、根據上一條,如果要在網路上傳輸或者存入磁碟,就涉及到str和bytes的轉換
bytes可以用b’ABC’表示 str通過encode()轉成指定編碼的bytes
如:’ABC’.encode(‘ascii’) 或 ‘中文’.encode(‘utf-8’)
如果從網路上讀取了位元組流或磁碟讀取了資料,讀取的是bytes,變成str要用decode
如:b’ABC’.decode(‘ascii’) 或b‘\xe4\xb8\xad’.decode(‘utf-8’, errors=’ignore’) errors不是必須的,寫了可以忽略錯誤位元組
19、計算str中包含的字元,用len(),如果是bytes型別的話,len()計算的是位元組數
20、python頭,指定是可執行程式和指定編碼
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
21、格式化 佔位符:%s 字串 %d 整形 %f 浮點型 %X 十六進位制
還可以指定補0和寬度限制%04d 寬度是4,不夠的補充0
%.9f 小數點後保留9位
%% 輸出百分號
22、另一種格式化 format()
23、增長百分比,計算公式是(當前-之前)/之前
24、如果沒有特殊要求,轉換的時候,牢記使用utf-8
25、list 有序集合,可以下標訪問,len獲取元素個數,最後一個可以用-1做索引,-2等類似
append()追加到最後clas.append(‘ee’)
insert()指定到索引的位置 clas.insert(2, ‘cc’) #切記是從0開始的,2指的是第三個位置
pop()刪除末尾
pop(i)刪除指定位置
賦值給對應下標直接把對應下標值替換掉
list裡面的元素型別可以不一樣 L = [‘app’, 111, True]
list元素可以是一個list M = [[1, ‘bb’], ‘aaa’, L]
26、tuple 和list類似,但是一旦初始化就不能修改
classmates = (‘aa’, ‘bb’, ‘cc’)
只有一個元素的tuple,要用clss = (1,) 切記一定要加逗號,否則會被當成計算結果的
cla = (‘A’, ‘B’, [C, D]) tuple裡面的list的值是可以變的 也就是cla[2][0] cla[2][1]可變,所謂的不可變是指向不可變,但是list本身可變,所以還是可以變化
由於tuple不可變,所以程式碼更安全,能用tuple代替list就代替
27、判斷 if elif else,切記後面都要加冒號
if age >= 6:
do something
elif age >18:
do something
else:
do something
28、input()返回的都是str,所以如果是輸入的int型別的,那就要用int(s)轉一下
s = input(‘birth:’)
birth = int(s)
29、迴圈
for x in names:
range(n) 生成從0 到 n-1的序列
while 條件:
30、break提前跳出迴圈 ,continue跳過本次,直接開始下一次
31、dict 字典,其他語言中的map,使用鍵值(key-value)儲存
d = {‘AA’:11, ‘BB’:22, ‘CC’:33}
d[‘DD’] = 44 直接就把新的key加進去了
d.get(‘AA’) 不存在返回None 可以指定當不存在時候的返回值 d.get(‘AA’, -1)
pop(key) 刪除指定key-value對
dict內部存放的順序和key放入的順序無關
32、dict 比較 list 優點,查詢插入快,不會隨著key增加而變慢,缺點是佔用記憶體大
dict 空間換時間,可以用在需要高速查詢的地方
dict的key是不可變物件,因此可以用字串、整數做key,不能用list做key
33、set 和dict類似,一組key的集合
建立,需要提供list作為輸入集合 s = set([1,2,3]) key是不能重複的,加了重複的相當於沒加
add(key)可以新增元素到set
s = set([1,2,3])
s.add(4)
remove(key) 刪除元素
set相當於集合,可以做交、或
s1 = set([1,2,3])
s2 = set([2,3,4])
s1 & s2
s1 | s2
34、不可變物件
對於不變物件來說,呼叫物件自身的任意方法,都不會改變物件自身的內容,相反,這些方法會建立新的物件並返回,所以不可變物件永遠不可變
35、資料型別轉換 int() float() str() bool()
36、函式名也可以賦值給一個變數 如 a = abs a(-1) 相當於給函式起了個別名
37、定義一個什麼事情都不做的空函式,可以用pass語句
def nop():
pass
38、isinstance() 可以判斷第一個引數是不是第二個引數裡面的型別,第二個引數可以是個tuple
eg: isinstance(x, (int, float))
39、python返回多個值的時候,其實是返回的一個tuple,只是語法上一個tuple可以省略括號
40、函式執行完畢,也沒有return 則 自動 return None
41、一元二次方程的解
42、可以指定預設引數,必須必選引數在前,預設引數在後
def power(x, y=2, z=4)
也可以不按順序提供部分預設引數
power(1, z=5)
43、預設引數大坑,一定不能指向可變的引數,如list
eg:def add_end(L = []):
L.append(‘END’)
return
可以更改成如下:
def add_end(L = None):
if L is None:
L = []
L.append(‘END’)
return L
44、不變物件的優勢
不能改,發生錯誤的可能大大降低
多工的時候,可以同時讀
45、可變引數,定義引數的個數可變的函式
def calc(*number): 這樣就可以了
46、如果已經有了一個list或者tuple,直接呼叫calc(*nums) 即可
47、關鍵字引數 ** 可以提供dict型別的引數
48、命名關鍵字引數
def person(name, age, *, city, job): 只接收city和job作為關鍵字的引數
49、任意函式,都可以通過類似func(*args, **kw)形式呼叫,無論引數如何定義
50、*args是可變引數,接收tuple
**kw是關鍵字引數,接收dict
51、切片 L = [‘AA’, ‘BB’, ‘CC’]
L[0:3] 從0開始取,但是不包括3 獲取的是0 1 2
0可以省略,同時也可以倒數取值 L[-2:]
倒數第一個元素的索引是-1
所以後10個是L[-10:]
還可以前10個,每兩個取一個 L[:10:2]
L[::5] 所有的每五個取一個
L[:] 原樣賦值
52、使用切片寫trim() 去除頭尾的空格
def trim(s):
while(s[:1] == ‘ ’):
s = s[1:]
while(s[-1:] == ‘ ’):
s = s[:-1]
return s
53、迭代
給定一個list或者tuple,我們通過for迴圈遍歷,這種遍歷稱為迭代
54、dict的迭代
dict預設迭代的是key for key in d:
dict想迭代value for value in d.values()
dict想兩個都迭代 for k,v in d.items()
55、判斷一個物件是可迭代物件,用collections 的Iterable型別判斷
from collections import Iterable
isinstance(‘abc’, Iterable)
56、list想同時迭代索引(下標)和元素本身
for i,v in enumerate([‘A’, ’B’, ’C’])
print(i, v)
輸出的結果會是 0 A\n1 B\n2 C(回車用\n代替了)
57、列表生成式List Comprehensions,可以建立list的生成式
[x * x for x in range(1,11)] 能生成 [1,4,9,…,100]
注意:range是不包括最右邊的邊界的
58、可以加上if判斷,篩選出你想要的
[x * x for x in range(1,11) if x%2 == 0] 這個結果是僅偶數的平方
59、兩層迴圈生成全排列
[x+y for x in ‘ABC’ for y in ‘XYZ’]
60、列出當前目錄下所有檔案和目錄名
import os
[d for d in os.listdir(‘.’)]
61、列表生成式也可以使用兩個變數生成list
d = {‘x’: ‘A’, ‘y’:’B’}
[x + ‘=’ + y for x, y in d.items()]
62、所有list變小寫
L = [‘Hello’, ‘World’]
[s.lower() for s in L]
63、L2 = [s.lower() for s in L1 if isinstance(s, str)] 只處理是str的防止出錯
64、生成器,一邊迴圈一邊計算的機制 generator
65、生成器建立方法一
生成式的中的[] 變為()
列印每一個元素使用next() ,eg:next(a) 最後丟擲StopIteration錯誤無法繼續
或者for迴圈,因為generator也是可迭代物件
66、yield 定義generator的另一種方法,函式定義中包含yield-》generator
呼叫的時候還是用for迴圈
67、可以直接作用於for迴圈的物件統稱為可迭代物件Iterable
list tuple dict set str 都是Iterable
68、可以被next()函式呼叫並不斷返回下一個值的物件成為迭代器Iterator
生成器都是Iterator物件,但是list dict str雖然是Iterable,但不是Iterator
變成Iterator 可以用iter()函式
69、Iterator物件表示的是一個數據流,是惰性的,只有需要返回下一個資料的時候才計算
70、python的for迴圈本質上是通過不斷呼叫next()函式實現的
71、函式名也是變數
f = abs
f(-1)
72、abs函式實際上是定義在import builtins模組,更改abs後,想讓abs變數的指向在其他模組也生效
用import builtins;builtins.abs = 10
73、傳入函式,一個函式接收另一個函式作引數,這種函式稱為高階函式
def add(x,y,f):
retrun f(x) + f(y)
74、編寫高階函式,就是讓函式的引數能夠接收別的函式
75、把函式作為引數傳入,這樣的函式成為高階函式,函數語言程式設計就是指這種高度抽象的程式設計正規化
76、map()函式接收兩個引數,一個是函式,一個是Iterable,map將傳入的引數一次作用到序列的每個元素,並把結果作為新的Iterator返回
map()第一個引數是f,即函式物件本身,返回的是Iterator,所以用list()函式轉換下,可以把結果返回成list
def f(x):
return x * x
r = map(f, [1,2,3])
list(r)
77、map()作為高階函式,把運算規則抽象了,比如把list所有數字轉字串
list(map(str, [1, 3, 4]))
78、reduce() 作用在一個序列[x1, x2, … ]上,函式接收兩個引數,reduce把結果序列和序列的下一個元素累計
reduce(f, [x1, x2, x3]) = f(f(x1, x2), x3)
79、序列求和
from functools import reduce
def add(x, y):
return x+y
reduce(add, [1, 3, 5, 7, 9])
80、[1, 3, 5, 7]轉成整數1357
from functools import reduce
def fn(x, y):
return x * 10 + y
reduce(fn, [1, 3, 5, 7])
81、str轉int
from functools import redece
def fn(x, y):
return x * 10 + y
def char2int(s):
digits = {'0': 0, '1': 1, '2': 2, '3': 3,'4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
return digits[s]
reduce(fn,map(char2int, ‘123675’))
82、上面的整理成函式(函式裡面可以巢狀函式)
from functools import reduce
DIGIT = {'0': 0, '1': 1, '2': 2, '3': 3,'4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def fn(x,y):
return x * 10 + y
def char2int(c):
return DIGIT[c]
reduce(fn, map(char2int, s))
上面還可以用lambda函式做一個簡化
83、**表示乘方
eg 10 **3 #表示10的3次方
84、filter()用於過濾序列,也接收一個函式,一個序列,作用於每個元素,根據True還是False決定留還是丟,如下刪掉偶數
def is_odd(n):
return n%2 == 1
list(filter(is_odd, [1, 2, 3, 4]))
85、刪掉空字串
def not_empty(s):
return s and s.strip()
list(filter(not_empty, [‘A’,’ ’, ‘C’, ‘ ’]))
86、生成素數
首先生成所有從3開始的奇數
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
定義一個篩選函式
def _not_divisible(n):
return lambda x:x %n > 0
最後,定義一個生成器,生成素數
def primes():
yield 2 #先生成個2,因為素數佇列是從3開始的
it = _odd_iter() #初始序列
while True:
n = next(it)
yield n
it = filter(_not_divisible(n), it)
87、判斷回數
def is_palindrome(n):
return str(n) == str(n)[::-1] #取反操作,牛掰
89、排序演算法sorted(),也是高階函式,可以接收一個key函式來實現自定義的排序
sorted([-1, 2,6,-3], key=abs)
結果[-1, 2, -3 ,6]
key指定的函式會作用於list的每一個元素上,並根據key函式返回結果排序,然後用sorted()函式按照新的list排序,然後按照對應關係返回list相應的元素
90、實現忽略大小寫的排序
sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)
91、反向排序,加上第三個引數reverse=True
sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower, reverse=True)
92、函式作為返回值
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum #直接把函式返回了
使用的時候, f = lazy_sum([1,2,3,7,9]) 這時候不計算,只是返回個函式
呼叫f() 才計算
內部函式可以引用外部的引數和區域性變數,每次呼叫都會返回新的函式
93、函式中定義函式,內部函式可以引用外部函式的引數和區域性變數,當外部函式返回內部函式時,相關的引數和變數都儲存在返回的函式中,這種程式結構稱為閉包
94、返回閉包的時候,要牢記一點,返回函式不要引用任何迴圈變數,或者後續會發生變化的變數(因為返回的函式是到呼叫的時候才執行的,如果之前變數有變化,那結果也會變)
95、如果非得呼叫變數,那麼再定義一個函式,把引數繫結到迴圈變數當前的值
def count():
def f(j):
def g():
return j * j
return g
fs = []
for i in range(1, 3):
fs.append(f(i))
return fs #返回一個函式的list
96、匿名函式lambda,限制是只能有一個表示式,不用寫return
好處是不用擔心函式名衝突
可以把匿名函式賦值給一個變數,後續可以呼叫變數
可以把匿名函式作為返回值返回
def build(x,y):
return lambda: x*x + y*y #這裡就不用加引數了
97、在程式碼執行期間動態增加功能的方式,稱為“裝飾器” Decorator,就是重新定義這個函式
def log(fn):
@functools.wraps(fn)
def wrapper(*args, **kw):
print(“%s run” % fn.__name__)
return fn(*args, **kw)
return wrapper
98、偏函式Partial (偏愛,把偏愛的引數給固定死)把一個函式的某些引數固定住(設定上預設值),返回一個新的函式
import functools
int2 = functools.partial(int, base=2) #直接就變成了int 2預設2進位制轉換。
99、模組
一個abc.py檔案就是一個名字叫abc的模組,xyz.py檔案是一個名字叫xyz的模組
如果這兩個模組和其他的模組名衝突了,我們可以通過包來組織模組,避免衝突,方法為選擇一個頂層包名,按照如下目錄存放:
mycompany
|-- __init__.py #必須存在,否則,Python會把目錄當成普通目錄,而不是包
|-- abc.py
|-- xyz.py
引入包後,只要頂層包名不和別人衝突,那所有模組都不會衝突
abc.py模組名變為mycompany.abc
xyz.py模組名變為mycompany.xyz
__init__.py 本身就是一個模組,模組名為mycompany ,可以是空檔案
自己建立的模組不能和Python自帶的模組名稱衝突,檢查方法直接在Python互動環境執行import abc,若成功則說明系統存在此模組
100、要新增自己的搜尋目錄,兩種方法
第一種直接修改sys.path,該方法執行時修改,執行結束失效
import sys
sys.path.append(‘/users/Michael/my_py_scripts’)
第二種設定環境變數PYTHONPATH