日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【python】速查手册(基础笔记) - 人生苦短,我用python

發布時間:2023/12/9 python 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【python】速查手册(基础笔记) - 人生苦短,我用python 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
python學習筆記:小甲魚python全套視頻 ?+ ?python基礎教程 第2版修訂版(書附10個大型案例)
python學習環境:(python3)win10下python3.5.4的IDLE ?+ ?ubuntu下python3輔助
python分享范圍:適合有C/C++/JAVA任意語言之一為基礎,不適合純新手入門
python語言優勢:至今還沒有一門編程語言,開發速度比Python快,運行速度比C快

python常用工具手冊:
http://bbs.fishc.com/forum.php?mod=collection&action=view&ctid=198

---------------------------------2017.08.27--------------------------------------
00丶python背景與特點
Python語言起源
在1989年末,Guido van Rossum為了打發圣誕節的無聊,創造了python(大蟒蛇)。 1991年,第一個 Python 版本誕生。最新版本是Python3 3.6.2 。Guido van Rossum 是蒙提·派森的飛行馬戲團(Monty Python‘s Flying Circus)的愛好者。logo是由兩只蟒蛇的圖形組成。


官網下載地址:
https://www.python.org/downloads/


Python 3 與 Python 2 不完全兼容
官方表示對 Python2 支持到2020年, Python2 2.7.13。Python 2 的生態庫遠遠大于 Python 3。


簡單:
學習曲線平滑, 45分鐘學會基本使用,使用簡單。
跨平臺:
一次編寫、到處運行。 Windows, Linux, Mac, Android
功能強大:
? ? 動態類型、自動內存管理
? ? 非常實用的內置對象類型
? ? 強大的內置工具和標準庫
? ? 易于擴展,很多成熟易用第三方庫
? ? 大型程序支持
應用廣泛:
? ? 數據庫、網絡、圖形圖像、科學計算、機器學習、web開發、操作系統擴展等
缺點:
運行速度不夠快(硬件的發展可以為此彌補不足)
開發速度與運行速度之間的矛盾:
至今還沒有一門編程語言,開發速度比Python快,運行速度比C快
知名軟件包:Django/Numpy/Pandas/Matplotlib/PIL (Pillow)/PyQt5/Tensorflow/Scipy/Theano/NLTK
知名項目:(網站)豆瓣/知乎/美團/Gmail/Youtube/Instagram/Calibre/……


01丶第一次親密接觸 first love
(1) win下的python IDLE集成開發環境自動縮進,table鍵補齊變量名
(2) linux下使用vi編輯.py的python文件,需要聲明 #!/usr/bin/python3
(3) python使用等量(1個tab)的縮進來嚴格對齊表示作用域
#!/usr/bin/python3
#guess game


print ("---------游戲開始-----------")
temp = input ("輸入一個我現在想的數字:")
guess = int (temp)
if guess == 8:
print ("猜對了!!!")
else:
print ("哈哈,猜錯了。。")
print ("游戲結束嘍~")
#---end---


BIF == Built-in functions(內置函數)
>>> dir(__builtins__)
..., 'input', ...
>>> help(input)
#可以查詢內置函數的說明和用法,類似于C語言的man手冊


02丶變量 variable
(1) python沒有"變量"只有"名字"
(2) 變量使用之前,需要對其先賦值
(3) 變量名命名同C的規則,不能以數字開頭,保證可讀性命名即可
(4) 大小寫敏感,區分
(5) =左右依次為左值和右值
(6) 十六進制,以0x 或 0X 開頭 ,數字由"0"到"9" 或者 "a"到"f" 或者 "A"到"F"組成
八進制,0o或0O 開頭,數字由"0" 到 "7"組成
二進制,0b或0B 開頭表示,數字由"0" 或者"1"組成
十進制由數字"0"到"9"組成,并且不能以0開頭
>>> teacher = 'jiangyuan'
>>> print (teacher)
jiangyuan
>>> teacher = 'somebody'
>>> print (teacher)
somebody
>>> first = 3
>>> second = 8
>>> third = first + second
>>> print (third)
11
>>> myteacher = 'jiangyuan'
>>> yourteacher = 'somebody'
>>> ourteacher = myteacher + yourteacher
>>> print (ourteacher)
jiangyuansomebody


03丶運算符及優先級 precedence of operator
#符合數學運算優先原則,括號最優先,最安全。
lambda lambda表達式
or 布爾或
and 布爾與
not 布爾非
in 和 not in 成員是否屬于測試
is 和 is not 對象是否是同一個
> ?>= ?< ?<= ?== ?!= 比較操作符
| 按位或
^ 按位異或
& 按位與
<< 和 >> 移位
+ 和 - 加法和減法
* 和 / 和 % 乘法、除法、取余
+x 和 -x 正負號
~x 按位翻轉
** 指數(冪運算)
// 地板除法,舍棄小數部分
---python運算符優先級(圖)---
#=連續賦值,自右向左,同C語言
>>> a = b = c = d = 10
>>> print (a, b, c, d)
10 10 10 10
>>> a += 1
>>> b -= 1
>>> c *= 10
>>> d /= 8 #真除法,精確值
>>> print (a, b, c, d)
11 9 100 1.25
>>> d = 10
>>> d // 3 ?#地板除法(Floor)舍棄小數部分
3
>>> 3 < 4 < 5 ?#支持連續判斷,不建議這樣用,可讀性不高
True
>>> 3 < 4 and 4 < 5
True


04丶類型 type
數值類型:整型(int)、浮點型(float)、布爾類型(bool)、e記法(科學計數法,屬于float)
(1) 整型與浮點型的區別就是是否含有小數點'.'
(2) bool類型的值是以大寫開頭的兩個單詞: True / False
(3) 純數字的字符串可以使用int轉為數字,進而參與計算,相當于C的atoi,非純數字的不能使用int轉換為數字
(4) float類型轉換為int類型時,會丟棄小數部分
(5) str類型均可被其他類型轉換,即變成字符串無障礙
(6) type (value) 返回變量類型,isinstance(value, type)類型判斷返回bool值


#float→int,丟棄小數部分
>>> a = 5.99
>>> b = int (a)
>>> print (b)
5


#e記法示例
>>> 0.00000000000000111
1.11e-15
>>> 150000000000
150000000000
>>> 15e10
150000000000.0


#isinstance類型判斷
>>> isinstance ('hello', str)
True
>>> isinstance (520, str)
False
>>> isinstance (520, int)
True


05丶條件分支與循環 condition and loop
條件bool值: True ?False
False 的值: False ?None ?0 ?"" ?() ?[] ?{}


if-else
if condition:
#condition == True, 執行的操作,可多層嵌套
else:
#condition == False, 執行的操作,可多層嵌套


if-elif-else
if condition:
#condition == True, 執行的操作,可多層嵌套
elif condition:
#condition == True, 執行的操作,可多層嵌套
else:
#condition == False, 執行的操作,可多層嵌套


x if condition else y ?#三元操作符
舉例:
>>> x, y = 4, 5
>>> small = x if x < y else y
>>> print (small)
4


assert 斷言
當assert關鍵字后面的條件為假的時候,程序自動崩潰并拋出AssertionError異常。
>>> assert 3 > 4
Traceback (most recent call last):
? File "<pyshell#160>", line 1, in <module>
? ? assert 3 > 4
AssertionError
>>> assert 3 < 4
>>>?


while 循環
while condition:
#condition == true, 執行的循環體操作
#condition == false, 循環體外的操作


for 循環
for target in expression:
#循環體
示例:
>>> favourite = 'string'
>>> for i in favourite:
print (i, end=' ') ?#end以空格隔開
s t r i n g


range()函數
range ([start], [stop], [step]) ?#step默認每次遞增1,且range的取值范圍到stop-1
常與for循環一起使用。
示例:
>>> for i in range (2, 5):
print (i, end=' ')
2 3 4
>>> for i in range (1, 10, 2):
print (i, end=' ')
1 3 5 7 9


break 和 continue
同C語言的break和continue,依次為跳出循環和跳過當前循環。


pass 和 del 和 exec
pass 什么也不敢,暫時預留
del 刪除不再使用的對象
exec 執行python語句
exal 計算python表達式,并返回結果值


06丶列表 list
普通列表:member = ['name', 'id', 'age', 'weight']
混合列表:mix = [1, 'name', 3.14, [1, 2, 3]]
空列表:empty = []
列表常用方法: len()/max()/min()/append()/extend()/insert()/remove()/pop()/count()/index()/reverse()/sort()


len()
功能:列表長度(元素個數)
len(listname)
>>> len(member)
4


append()
功能:向列表添加單個元素
listname.append(element)
>>> member.append('class')
>>> member
['name', 'id', 'age', 'weight', 'class']


extend()
功能:使用子列表擴展列表
listname.extend([element1, element2, ...])
>>> member.extend (['str1', 'str2'])
>>> member
['name', 'id', 'age', 'weight', 'class', 'str1', 'str2']


insert()
功能:向列表指定位置插入元素
listname.insert(position, element)
#list和數組一樣,下標/索引均從0開始
>>> member.insert (1, 'new_elem')
>>> member
['name', 'new_elem', 'id', 'age', 'weight', 'class', 'str1', 'str2']


列表元素訪問
listname[index]
#index從0開始,到index-1位置的索引訪問


列表元素刪除
listname.remove(element) #刪除元素element
del listname[index] #刪除index位置的元素
listname.pop() #刪除最后一個元素,相當于C語言的彈棧
listname.pop(index) #刪除index位置指定的元素


列表元素分片
listname[start_index:stop_index]
(1) 分片不會修改原列表的值,輸出的是一份拷貝
(2) 分片輸出的是從 start_index 到 stop_index-1 位置的值
(3) 分片的start和stop位置均可省略,start省略表示從頭取值,stop省略表示取值到結尾,都省略表示取列表所有的值
示例:
>>> member = ['name', 'id', 'age', 'weight', 'class', 'str1', 'str2', 'str3']
? ? ? ? ? ? ? ?0 ? ? ? 1 ? ? 2 ? ? ?3 ? ? ? ? 4 ? ? ? ?5 ? ? ? 6 ? ? ? 7
>>> member[1:3]
['id', 'age']
>>> member[1:]
['id', 'age', 'weight', 'class', 'str1', 'str2', 'str3']
>>> member[:3]
['name', 'id', 'age']
>>> member[:]
['name', 'id', 'age', 'weight', 'class', 'str1', 'str2', 'str3']
>>> member[5:len(member)] #訪問最后3個元素
['str1', 'str2', 'str3']
>>> member[0:len(member):2] #最后的2代表步長
['name', 'age', 'class', 'str2']


列表常用操作符
(1) list元素的判斷只會判斷第一個元素,然后理解返回bool結果
(2) list支持比較、邏輯、連接(+)、重復(*)、成員關系(in)操作符
(3) list賦值list時需要注意加上[:],左值會表現為一份拷貝
示例:
list2 = list1[:]#list2是list1的一份拷貝
list3 = list1 #list3是list1的一個引用(list1被修改,list3也會跟著被修改)
(4) dir(list) 查看list支持的所有方法:
listname.count(element)#element元素出現的次數
listname.index(element, [range_s], [rang_t])#查找元素在起止范圍里第一次出現的下標位置
listname.reverse()#將list中的元素原地翻轉
listname.sort()#將list中的元素進行排序,默認從小到大(修改原list內容)
listname.sort(reverse=True)#排序元素,實現從大到小(修改原list內容)


07丶元組 tuple
元組和列表使用上相似:
(1) 最大區別:列表可以任意修改和插入等操作,元組是不可改變的
(2) 創建:列表使用[],元組使用()
元組只有1個元素時使用(element,)注意逗號
()可以省略,但是,逗號不能省略
(3) 訪問:都使用name[index]來訪問
(4) 元組在映射中當做鍵使用,而列表不行
示例:
>>> temp = 1,
>>> type (temp)
<class 'tuple'>
>>> 8 * (8)
64
>>> 8 * (8,)
(8, 8, 8, 8, 8, 8, 8, 8) ?#重復元組
#元組元素插入
>>> temp = ('name1','name2','name3','name4')
>>> temp = temp[:2] + ('new_name',) + temp[2:]
>>> temp
('name1', 'name2', 'new_name', 'name3', 'name4')


08丶字符串 ?string
(1) \可以進行符號轉義
(2) 單引號等同于雙引號
(3) 定義字符串時使用r寫在右值前面聲明為原始字符串
(4) 使用三引號('''或""")可以指定多行字符串。并且字符串里可以包含單引號和雙引號'''
(5) +號運算符可以連接字符串為1個字符串
(6) *號運算符可以復制多個相同字符串
列表和元組應用于字符串,所有標準的序列操作均適用于字符串。
>>> str1 = 'hello, python!' ?#字符串相當于元素是字符的元組
>>> str1 = str1[:5] + ';' + str1[5:]
>>> str1
'hello;, python!'


字符串常用方法: find()/join()/lower()/replace()/split()/strip()/translate()/
>>> dir(str)
...'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'...
【F1】可以從python的幫助文檔中【索引】查找操作方法的介紹內容及舉例。


capitalize() 返回新字符串,把字符串的第一個字符改為大寫
casefold() 返回新字符串,把整個字符串的所有字符改為小寫
center(width) 將字符串居中,并使用空格填充至長度 width 的新字符串
count(sub[, start[, end]]) 返回 sub 在字符串里邊出現的次數,start 和 end 參數表示范圍,可選。
encode(encoding='utf-8', errors='strict') 以 encoding 指定的編碼格式對字符串進行編碼。
endswith(sub[, start[, end]]) 檢查字符串是否以 sub 子字符串結束,如果是返回 True,否則返回 False。start 和 end 參數表示范圍,可選。
expandtabs([tabsize=8]) 把字符串中的 tab 符號(\t)轉換為空格,如不指定參數,默認的空格數是 tabsize=8。
find(sub[, start[, end]]) 檢測 sub 是否包含在字符串中,如果有則返回索引值,否則返回 -1,start 和 end 參數表示范圍,可選。
index(sub[, start[, end]]) 跟 find 方法一樣,不過如果 sub 不在 string 中會產生一個異常。
isalnum() 如果字符串至少有一個字符并且所有字符都是字母或數字則返回 True,否則返回 False。
isalpha() 如果字符串至少有一個字符并且所有字符都是字母則返回 True,否則返回 False。
isdecimal() 如果字符串只包含十進制數字則返回 True,否則返回 False。
isdigit() 如果字符串只包含數字則返回 True,否則返回 False。
islower() 如果字符串中至少包含一個區分大小寫的字符,并且這些字符都是小寫,則返回 True,否則返回 False。
isnumeric() 如果字符串中只包含數字字符,則返回 True,否則返回 False。
isspace() 如果字符串中只包含空格,則返回 True,否則返回 False。
istitle() 如果字符串是標題化(所有的單詞都是以大寫開始,其余字母均小寫),則返回 True,否則返回 False。
isupper() 如果字符串中至少包含一個區分大小寫的字符,并且這些字符都是大寫,則返回 True,否則返回 False。
join(sub) 以字符串作為分隔符,插入到 sub 中所有的字符之間。
ljust(width) 返回一個左對齊的字符串,并使用空格填充至長度為 width 的新字符串。
lower() 轉換字符串中所有大寫字符為小寫。
lstrip() 去掉字符串左邊的所有空格
partition(sub) 找到子字符串 sub,把字符串分成一個 3 元組 (pre_sub, sub, fol_sub),如果字符串中不包含 sub 則返回 ('原字符串', '', '')
replace(old, new[, count]) 把字符串中的 old 子字符串替換成 new 子字符串,如果 count 指定,則替換不超過 count 次。
rfind(sub[, start[, end]]) 類似于 find() 方法,不過是從右邊開始查找。
rindex(sub[, start[, end]]) 類似于 index() 方法,不過是從右邊開始。
rjust(width) 返回一個右對齊的字符串,并使用空格填充至長度為 width 的新字符串。
rpartition(sub) 類似于 partition() 方法,不過是從右邊開始查找。
rstrip() 刪除字符串末尾的空格。
split(sep=None, maxsplit=-1) 不帶參數默認是以空格為分隔符切片字符串,如果 maxsplit 參數有設置,則僅分隔 maxsplit 個子字符串,返回切片后的子字符串拼接的列表。
splitlines(([keepends])) 按照 '\n' 分隔,返回一個包含各行作為元素的列表,如果 keepends 參數指定,則返回前 keepends 行。
startswith(prefix[, start[, end]]) 檢查字符串是否以 prefix 開頭,是則返回 True,否則返回 False。start 和 end 參數可以指定范圍檢查,可選。
strip([chars]) 刪除字符串前邊和后邊所有的空格,chars 參數可以定制刪除的字符,可選。
swapcase() 翻轉字符串中的大小寫。
title() 返回標題化(所有的單詞都是以大寫開始,其余字母均小寫)的字符串。
translate(table) 根據 table 的規則(可以由 str.maketrans('a', 'b') 定制)轉換字符串中的字符。
upper() 轉換字符串中的所有小寫字符為大寫。
zfill(width) 返回長度為 width 的字符串,原字符串右對齊,前邊用 0 填充。


字符串操作:格式化
(1) 通過format方法將位置參數傳遞給對應字段
(2) : 冒號表示格式化符號的開始


位置參數:{0~n}
>>> "{0} love {1},{2}.".format("I", "you", "too")
'I love you,too.'


關鍵字參數:{自定義}
>>> "{a} love {b}, {c}.".format(a="I", b="you", c="too")
'I love you, too.'
注意:位置參數和關鍵字參數可以同時使用,但位置參數必須在關鍵字參數的前面。


字符串格式化符號含義
%c 格式化字符及其 ASCII 碼
%s 格式化字符串
%d 格式化整數
%o 格式化無符號八進制數
%x 格式化無符號十六進制數
%X 格式化無符號十六進制數(大寫)
%f 格式化浮點數字,可指定小數點后的精度,默認精確到小數點后6位
%e 用科學計數法格式化浮點數
%E 作用同 %e,用科學計數法格式化浮點數
%g 根據值的大小決定使用 %f 或 %e
%G 作用同 %g,根據值的大小決定使用 %f 或者 %E
舉例:
>>> '%c' % 97 # 此處 % 為占位符,同C語言中printf函數中的%
'a'
>>> '%c %c %c' % (97, 98, 99) #此處的元組()小括號不能省略
'a b c'


格式化操作符輔助命令
m.n m 是顯示的最小總寬度,n 是小數點后的位數
- 用于左對齊
+ 在正數前面顯示加號(+)
# 在八進制數前面顯示 '0o',在十六進制數前面顯示 '0x' 或 '0X'
0 顯示的數字前面填充 '0' 取代空格
舉例:
>>> '%5.1f' % 27.658 #m.n
' 27.7'
>>> '%-10d' % 5 #填充的位數都是空格
'5 ? ? ? ? ?'
>>> '%#x' % 160 #對應進制顯示方式
'0xa0'
>>> '%010d' % 5 #用0填充。'%-010d' % 5 負號的時候填充的只會是空格
'0000000005'


Python 的轉義字符及其含義
\' 單引號
\" 雙引號
\a 發出系統響鈴聲
\b 退格符
\n 換行符
\t 橫向制表符(TAB)
\v 縱向制表符
\r 回車符
\f 換頁符
\o 八進制數代表的字符
\x 十六進制數代表的字符
\0 表示一個空字符
\\ 反斜杠


09丶序列方法 sequence method
列表、元組、字符串的共同點:
(1) 都可以通過索引得到每一個元素
(2) 默認索引值總是從0開始
(3) 可以通過分片的方法得到一個范圍內的元素的集合
(4) 有很多共同的操作符(重復*、拼接+、成員關系in/not in等)
(5) 統稱為序列,以下(成員函數)為序列方法


list()
list(iterable) 把一個可迭代對象轉換為列表
舉例:
>>> b = 'I love you.' # b也可以是元組 b = (1, 2, 3, 4, 5)
>>> b = list(b)
>>> b
['I', ' ', 'l', 'o', 'v', 'e', ' ', 'y', 'o', 'u', '.']


tuple()
tuple(iterable) 把一個可迭代對象轉換為元組
舉例:
>>> b = 'I love you.'
>>> b = tuple(b)
>>> b
('I', ' ', 'l', 'o', 'v', 'e', ' ', 'y', 'o', 'u', '.')


max(...) 返回集合或者序列中的最大值(要求類型一致)
min(...) 返回集合或者序列中的最小值(要求類型一致)
>>> max(iterable, *[, default=obj, key=func]) -> value
>>> max(arg1, arg2, *args, *[, key=func]) -> value
舉例:
>>> numbers = [1, 18, 13, 0, -98, 34, 53, 76, 32]
>>> max(numbers)
76
>>> min(numbers)
-98


sum(...) 返回序列iterable和可選參數的總和(要求類型一致)
>>> sum(iterable, start=0, /)
舉例:
>>> tuple1 = (3.1, 2.3, 3.4)
>>> sum(tuple1)
8.8
>>> sum(tuple1, 0.2) #0.2為可選參數,會加在一起
9.0


sorted(...) 返回序列的排序結果
>>> sorted(iterable, /, *, key=None, reverse=False)
舉例:
>>> tuple1 = (3.1, 2.3, 3.4)
>>> sorted(tuple1)
[2.3, 3.1, 3.4]


reversed(...) 翻轉一個序列的內容
>>> reversed(sequence)
舉例:
>>> numbers = [1, 24, 5, -98, 54, 32]
>>> reversed(numbers)
<list_reverseiterator object at 0x000002C3EE5046A0>#這種格式都是:迭代器對象
>>> list(reversed(numbers)) # 將迭代器對象轉換為list列表
[32, 54, -98, 5, 24, 1]


enumerate(...) 生成由序列組成的元組
>>> enumerate(iterable[, start])
舉例:
>>> numbers = [1, 24, 5, -98, 54, 32]
>>> list(enumerate(numbers))
[(0, 1), (1, 24), (2, 5), (3, -98), (4, 54), (5, 32)]


zip(...) 返回由各個參數的序列組成的元組
>>> zip(iter1 [,iter2 [...]])
舉例:
>>> a = [1, 2, 3, 4, 5, 6, 7, 8]
>>> b = [4, 5, 6, 7, 8]
>>> zip(a, b)
<zip object at 0x000002C3EE562948>
>>> list(zip(a, b))
[(1, 4), (2, 5), (3, 6), (4, 7), (5, 8)]
>>> for i,j in zip(a, b): ?#并行迭代,同時迭代兩個變量
print(str(i) + ' is ' + str(j))
1 is 4
2 is 5
3 is 6
4 is 7
5 is 8


10丶函數 function
(1) python只有函數(return)沒有過程(no return)
(2) 函數返回多個值的時候,使用list列表或tuple元組進行返回
(3) 局部變量和全局變量的規則同C語言
(4) 在函數內部使用 global 修飾變量,使函數可以修改同名的全局變量
(5) 函數嵌套時,內部函數的作用域都在外部函數之內,出了外部函數就不能被調用


函數定義和調用
def function_name():
#函數體內容
function_name() #函數調用,執行函數體的內容


函數返回值
def function_name():
#函數體中返回
return value
print(function_name()) #調用函數并打印其返回值


函數參數
def function_name(param): #形參:多個參數使用,逗號隔開
#函數體使用參數param
function_name(parameter) #實參:傳遞實際參數


函數文檔
舉例:
>>> def my_sec_func(name):
'function document.'#函數文檔部分,單引號引起來即可
print(name)
>>> my_sec_func('myname')
myname
>>> my_sec_func.__doc__ ?#打印輸出函數文檔部分
'function document.'
>>> help(my_sec_func)
Help on function my_sec_func in module __main__:
my_sec_func(name)
? ? function document.


關鍵字參數與默認參數
舉例:
>>> def say_some(name, words):
#>> def say_some(name='abc', words='string'): #形參可設置默認值
print(name + ' -> ' + words)
>>> say_some('Jan', 'learning python.')
Jan -> learning python.
>>> say_some(words='learning python.', name='Jan') #指定形參對應實參
Jan -> learning python.
#>>> say_some()
#abc -> string


*params搜集其余的位置參數
>>> def test(*params): # *params把實參打包為元組
print('len = ', len(params))
print('second params = ', params[1])
>>> test(1, 'Jan', 3.14)
len = ?3
second params = ?Jan
#搜集參數param加上普通形參
>>> def test(*params, tmp):
print('len = ', len(params))
print('second params = ', params[1])
print('tmp = ', tmp)
>>> test(1, 'Jan', 3.14, tmp = 520) #注意傳參需要單獨指定
len = ?3
second params = ?Jan
tmp = ?520


global 關鍵字
舉例:
>>> cnt = 5
>>> def my_func():
global cnt
cnt= 10
print(cnt)
>>> my_func()
10
>>> print(cnt)
10


函數嵌套
舉例:
>>> def func1():
print('func1 called...')
def func2():
print('func2 called...')
func2()
>>> func1() #調用func1
func1 called...
func2 called...


閉包closure
舉例1:
>>> def funX(x):
def funY(y):
return x * y
return funY
>>> i = funX(8)
>>> i
<function funX.<locals>.funY at 0x000001EFE75E87B8>
>>> type(i)
<class 'function'>
>>> i(5)
40
>>> funX(8)(5)
40
>>> funY(5) #不可被調用,解決辦法有2:list或者nonlocal
舉例2 - list:
>>> def fun1():
x = [5] #對func2函數來說x是全局變量,在func2中沒有定義x,是用list即可安全
def fun2():
x[0] *= x[0]
return x[0]
return fun2()
>>> fun1()
25
舉例2 - nonlocal:
>>> def fun1():
x = 5
def fun2():
nonlocal x #在內部函數中聲明x為非局部變量,再調用func1()也是安全的
x *= x
return x
return fun2()
>>> fun1()
25


lambda 表達式(匿名函數)
(1) 不需要考慮函數名的命名問題
(2) 極大簡化函數編寫的步驟
舉例:
>>> def ds(x):
return 2*x + 1
>>> ds(5)
11
>>> lambda x : 2*x + 1
<function <lambda> at 0x000002170B3D87B8> #可以理解為返回的是C語言的函數指針
>>> g = lambda x : 2*x + 1 #賦值后,傳參即可,g相當于接收了匿名函數
>>> g(5)
11
>>> g = lambda x, y : x+y #lambda匿名函數多個參數
>>> g(1, 3)
4


兩個牛逼的BIF:filter和map
(1) filter 過濾:返回其函數為真的元素的列表
>>> filter(function or None, iterable)
舉例:
>>> filter(None, [1, 0, False, True])
<filter object at 0x000001CE5BCB0710>
>>> list(filter(None, [1, 0, False, True]))
[1, True] #驗證filter過濾的是非true的內容
>>> def odd(x):
return x % 2
>>> temp = range(10)
>>> show = filter(odd, temp)
>>> list(show)
[1, 3, 5, 7, 9]
>>> list(filter(lambda x : x % 2, range(10))) ?#簡化一行實現求奇數
[1, 3, 5, 7, 9]


(2) map 映射:對序列中每個元素都應用函數
>>> list(map(lambda x : x + 2, range(10)))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]




---------------------------------2017.08.28--------------------------------------
11丶遞歸 recursion
#遞歸求階乘:
def factorial(n):
? ? if n == 1:
? ? ? ? return 1 #(1)必須包含退出條件,同C語言
? ? else:
? ? ? ? return n * factorial(n-1) #(2)必須調用函數自身,同C語言
number = int(input("請輸入一個正整數:"))
result = factorial(number)
print("%d 的階乘為:%d" % (number, result))
#運行:
請輸入一個正整數:10
10 的階乘為:3628800


斐波那契數列(遞歸)
def fab(n):
? ? if n < 1:
? ? ? ? print("input error!")
? ? ? ? return -1
? ? if n == 1 or n == 2:
? ? ? ? return 1
? ? else:
? ? ? ? return fab(n-1) + fab(n-2)
num = int(input("請輸入一個數字:"))
result = fab(num)
print("斐波那契數列結果為:%d" % result)


漢諾塔游戲(遞歸)
def hanoi(n, x, y, z):
? ? if n == 1:
? ? ? ? print(x, '-->', z)
? ? else:
? ? ? ? hanoi(n-1, x, y, z) ? ? #將前n-1個盤子從x移動到y上
? ? ? ? print(x, '-->', z) ? ? ?#將最底下的最后一個盤子從x移動到z上
? ? ? ? hanoi(n-1, y, x, z) ? ? #將y上的n-1個盤子移動到z上


n = int(input('請輸入漢諾塔的層數:'))
hanoi(n, 'x', 'y', 'z')




---------------------------------2017.08.29--------------------------------------
12丶字典 dict
(1) 字典是一種映射類型(key:value 鍵值映射項),類型名為 dict
(2) 字典的表示使用{}大括號,元素映射之間使用:冒號,使用dictname[]訪問字典映射的值
(3) 新建字典有兩種方法:三層小括號,一層小括號中key=value
(4) 字典中的鍵值映射項是無序的,popitem時是隨機彈出
(5) 字典基本操作:
len(d) 返回d中項的數量
d[k] 返回映射到鍵k上的值
d[k]=v 將值v映射到鍵k上
del d[k] 刪除鍵為k的項
k in d 檢查d中是否含有鍵為k的項
(6) 字典常用方法: clear()/copy()/fromkeys()/get()/has_key()/items()/iteritems()/keys()/iterkeys()/pop()/popitem()/setdefault()/update()/values()/itervalues()


映射關系示例
>>> brand = ['李寧', '耐克', '阿迪達斯', 'xx工作室']
>>> slogan = ['一切皆有可能', 'Just do it', 'Impossible is nothing', '讓編程改變世界']
>>> print('魚c工作室的口號是: ', slogan[brand.index('xx工作室')])
xx工作室的口號是: ?讓編程改變世界
#使用字典來完成映射工作
>>> dict1 = {'李寧':'一切皆有可能', '耐克':'Just do it', '阿迪達斯':'Impossible is nothing', 'xx工作室':'讓編程改變世界'}
>>> print('xx工作室的口號是: ', dict1['xx工作室'])
xx工作室的口號是: ?讓編程改變世界
#新建一個字典方法1:dict(((key1, value1), (key2, value2), ...))
>>> dictname = dict((('y', 1), ('u', 2), ('a', 3), ('n', 4)))
>>> dictname
{'u': 2, 'a': 3, 'y': 1, 'n': 4}
#新建一個字典方法2:(key1=value1, key2=value2, ...)
>>> dictname = dict(蒼井空='讓AV改變宅男', 工作室='讓編程改變世界')
>>> dictname
{'工作室': '讓編程改變世界', '蒼井空': '讓AV改變宅男'}
>>> dictname['蒼井空']
'讓AV改變宅男'
#字典中新增映射元素
>>> dictname['愛迪生'] = '天才是99%的汗水+1%的靈感,但這1%的靈感比99%的汗水更重要。'
>>> dictname
{'工作室': '讓編程改變世界', '愛迪生': '天才是99%的汗水+1%的靈感,但這1%的靈感比99%的汗水更重要。', '蒼井空': '讓AV改變宅男'}


字典中鍵、值、鍵值映射項的訪問
>>> dict1 = dict1.fromkeys(range(10), '贊')
>>> dict1
{0: '贊', 1: '贊', 2: '贊', 3: '贊', 4: '贊', 5: '贊', 6: '贊', 7: '贊', 8: '贊', 9: '贊'}
>>> for eachKey in dict1.keys():
print(eachKey, end=' ')
0 1 2 3 4 5 6 7 8 9
>>> for eachValue in dict1.values():
print(eachValue, end=' ')
贊 贊 贊 贊 贊 贊 贊 贊 贊
>>> for eachItems in dict1.items():
print(eachItems, end=' ')
(0, '贊') (1, '贊') (2, '贊') (3, '贊') (4, '贊') (5, '贊') (6, '贊') (7, '贊') (8, '贊') (9, '贊')


fromkeys(...) ?創建并返回一個新的字典
dictname.fromkeys(S[, V])
@S key;@V value 可選參數
舉例:
>>> dict1 = {}
>>> dict1.fromkeys((1, 2, 3))
{1: None, 2: None, 3: None}
>>> dict1.fromkeys((1, 2, 3), 'number')
{1: 'number', 2: 'number', 3: 'number'}
>>> dict1.fromkeys((1, 2, 3), ('one', 'two', 'three'))
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
>>> dict1.fromkeys((1, 3), 'num')
{1: 'num', 3: 'num'} ? #還是返回新的字典,并不會修改dict1


get(...) ?從字典中找到key的映射值value
舉例:
>>> dict1 = dict.fromkeys(range(10), 'Yes!')
>>> dict1
{0: 'Yes!', 1: 'Yes!', 2: 'Yes!', 3: 'Yes!', 4: 'Yes!', 5: 'Yes!', 6: 'Yes!', 7: 'Yes!', 8: 'Yes!', 9: 'Yes!'}
>>> dict1.get(10)
>>> print(dict1.get(10))
None
>>> dict1.get(10, '木有')
'木有'
>>> dict1.get(9, '木有')
'Yes!'


setdefault(...) ?類似于get但在字典里如果找不到的話會將映射項添加到字典中
dictname.setdefault(key, value)
舉例:
>>> a
{3: 'three', 4: 'four'}
>>> a.setdefault(5, '小白')
'小白'
>>> a
{3: 'three', 4: 'four', 5: '小白'}


clear() ?清空一個字典(包括使用當前字典賦值的其他字典)
舉例:
>>> dict1.clear()
>>> dict1
{}


copy() ?拷貝一個字典(淺拷貝,不受字典修改影響)
>>> a = {1:'one', 2:'two', 3:'three'}
>>> b = a.copy()
>>> c = a #相當于C的指針,C++的引用,修改字典c的值會同時影響字典a
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> c
{1: 'one', 2: 'two', 3: 'three'}
>>> print(id(a), id(b), id(c))
2334673012680 2334672609672 2334673012680
>>> c[4] = 'four'
>>> c
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}


pop(...) ?給定一個鍵彈出一個值
popitem() ?隨機彈出一個項(映射關系的鍵和值)
舉例:
>>> a
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a.pop(2)
'two'
>>> a
{1: 'one', 3: 'three', 4: 'four'}
>>> a.popitem()
(1, 'one')
>>> a
{3: 'three', 4: 'four'}


update(...) ?使用一個子字典去更新原字典
dictname1.update(dictname2)
舉例:
>>> a
{3: 'three', 4: 'four', 5: '小白'}
>>> b = {'小白':'狗'}
>>> a.update(b)
>>> a
{'小白': '狗', 3: 'three', 4: 'four', 5: '小白'}


13丶集合 set
(1) 使用{}創建的沒有映射關系的字典,成為集合類型,如num = {1, 2, 3, 4, 5}
(2) 集合中元素唯一,重復的數據會被自動清理掉
(3) 集合中元素無序,不能索引取到其元素的值
(4) 集合使用關鍵字 set([]) 來創建
(5) 集合支持 in 和 not in 來判斷是否屬于集合


舉例:
>>> num = {}
>>> type(num)
<class 'dict'>
#set沒有體現字典的映射
>>> num1 = {1, 2, 3, 4, 5}
>>> type(num1)
<class 'set'>
#set唯一性
>>> num2 = {1, 2, 3, 4, 2, 3, 5, 1, 5, 5}
>>> num2
{1, 2, 3, 4, 5}
#set無序性
>>> num2[2]
TypeError: 'set' object does not support indexing
#set關鍵字創建集合
>>> set1 = set([1, 2, 3, 4, 5, 5, 5, 3, 1])
>>> set1
{1, 2, 3, 4, 5}
#list實現set的唯一性
>>> num1 = [1, 2, 3, 4, 5, 5, 3, 1, 0]
>>> temp = []
>>> for each in num1:
if each not in temp:
temp.append(each)
>>> temp
[1, 2, 3, 4, 5, 0]
#簡化: 實現set的唯一性,并且會把set的無序性變為有序
>>> num1
[1, 2, 3, 4, 5, 5, 3, 1, 0]
>>> num1 = list(set(num1))
>>> num1
[0, 1, 2, 3, 4, 5]


add(...) ?往集合中加入元素
remove(...) ?從集合中刪除指定元素
舉例:
>>> num2
{1, 2, 3, 4, 5}
>>> num2.add(6)
>>> num2
{1, 2, 3, 4, 5, 6}
>>> num2.remove(4)
>>> num2
{1, 2, 3, 5, 6}


frozenset(...) ?將集合設置為不可變集合,frozen:冰凍的,凍結的
舉例:
>>> num3 = frozenset([1, 2, 3, 4, 5])
>>> num3
frozenset({1, 2, 3, 4, 5})
>>> num3.add(6)
AttributeError: 'frozenset' object has no attribute 'add'


集合內建方法(整理出來):
http://bbs.fishc.com/forum.php?mod=viewthread&tid=45276&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


14丶文件操作 file operation
open(...) ?打開一個文件返回一個流對象
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) ?#除了file參數,其他參數均有默認值
'r' 只讀模式
'w' 寫入(會覆蓋已存在的文件)模式
'x' 文件存在,報異常的模式
'a' 寫入(文件存在則追加)模式
'b' 二進制模式
't' 文本模式
'+' 可讀寫模式(可添加到其他模式)
'U' 通用換行符支持


舉例:
#打開一個文件,注意路徑的中\反斜杠的轉義(或用/斜杠一根即可)
>>> f = open('C:\\Users\\Jan\\Desktop\\IP.txt')
>>> f
<_io.TextIOWrapper name='C:\\Users\\Jan\\Desktop\\IP.txt' mode='r' encoding='cp936'>


文件對象方法
(整理)
http://bbs.fishc.com/forum.php?mod=viewthread&tid=45279&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403
(1) 文件對象支持直接使用list轉換讀出
(2) 文件對象支持 for...in 的迭代方式讀取


舉例:
>>> f = open('C:\\Users\\Jan\\Desktop\\IP.txt') #f,打開的文件流對象
>>> f.read()
'【本機】\nIP:192.168.31.217\n[ Ctrl + r ]\ncmd\nping 192.168.31.207\nmstsc\n\n\n【虛擬機】 - 虛擬網絡編輯器(自動) - 橋接模式\nIP:192.168.31.207\nlinux賬戶:jiangyuan\nlinux密碼:123456\n'
>>> f.read()
''
>>> f.close()
>>> f = open('C:\\Users\\Jan\\Desktop\\IP.txt')
>>> f.read(5)
'【本機】\n'
>>> f.tell()
10
>>> f.seek(45, 0) #0,文件起始位置;45,偏移字節數。從文件起始位置偏移一定量字節
45
>>> f.readline()
'md\n'
>>> list(f)
['ping 192.168.31.207\n', 'mstsc\n', '\n', '\n', '【虛擬機】 - 虛擬網絡編輯器(自動) - 橋接模式\n', 'IP:192.168.31.207\n', 'linux賬戶:jiangyuan\n', 'linux密碼:123456\n']
>>> for each_line in f:
print(each_line)#逐行讀取文件內容的高效方法
【本機】
IP:192.168.31.217
[ Ctrl + r ]
cmd
ping 192.168.31.207
mstsc
...
#創建一個新的可寫入的文件,寫入內容,然后關閉文件流對象
>>> f = open('C:\\Users\\Jan\\Desktop\\test.txt', 'w')
>>> f.write('some lines')
10
>>> f.close()


任務:將文件record.txt中的數據進行分割并且按照規律保存起來。
record.txt下載:
鏈接:http://pan.baidu.com/s/1sjzAhNR (密碼:tf2e)


#最終代碼如下:
def save_file(boy, girl, count):
? ? # 文件的分別保存操作
? ? file_name_boy = 'boy_' + str(count) + '.txt'
? ? file_name_girl = 'girl_' + str(count) + '.txt'


? ? boy_f = open(file_name_boy, 'w')
? ? girl_f = open(file_name_girl, 'w')


? ? boy_f.writelines(boy)
? ? girl_f.writelines(girl)


? ? boy_f.close()
? ? girl_f.close()


def split_file(filename):
? ? f = open(filename)


? ? boy = []
? ? girl = []
? ? count = 1


? ? for each_line in f:
? ? ? ? if each_line[:6] != '======':
? ? ? ? ? ? # 我們再這里進行字符串分割操作
? ? ? ? ? ? (role, line_spoken) = each_line.split(':', 1) ?#中文冒號:否則會報錯
? ? ? ? ? ? if role == '小甲魚':
? ? ? ? ? ? ? ? boy.append(line_spoken)
? ? ? ? ? ? if role == '小客服':
? ? ? ? ? ? ? ? girl.append(line_spoken)
? ? ? ? else:
? ? ? ? ? ? save_file(boy, girl, count)


? ? ? ? ? ? boy = []
? ? ? ? ? ? girl = []
? ? ? ? ? ? count += 1


? ? save_file(boy, girl, count)
? ? f.close()


split_file('C:\\Users\\Jan\\Desktop\\python_study\\record.txt')


文件操作練習題及答案(偽代碼可以保存一下):
http://blog.csdn.net/junwei0206/article/details/44988195


---------------------------------2017.08.30--------------------------------------
15丶模塊 modules
(1) 模塊是.py的python文件
(2) 使用模塊是需要進行導入,使用關鍵字 import


舉例:
>>> import random
>>> secret = random.randint(1, 10)
>>> secret
3


os 模塊(系統模塊)


os模塊方法表格:http://bbs.fishc.com/thread-45512-1-2.html


舉例:
>>> import os
>>> os.getcwd() ?#輸出當前工作目錄
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35'
>>> os.chdir('E:\\') ?#改變工作目錄
>>> os.getcwd()
'E:\\'
>>> os.listdir('E:\\') ?#列舉指定目錄中的文件名
['$RECYCLE.BIN', '.cache', '360Downloads', 'Jan_mi', 'Jan個人總資料', 'Qiyi', 'QQMusicCache', 'qycache', 'System Volume Information', 'Youku Files', 'Youxun', '博客'] ?#RECYCLE.BIN是個回收站
>>> os.mkdir('E:\\A') ?#創建單層目錄,如該目錄已存在拋出異常
>>> os.mkdir('E:\\A\\B')
>>> os.mkdir('E:\\C\\D')
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'E:\\C\\D'
>>> os.remove('E:\\A\\B\\test.txt') ?#刪除文件
>>> os.rmdir('E:\\A\\B\\') ?#刪除單層目錄,如該目錄非空則拋出異常
>>> os.system('cmd') ?#運行系統的shell命令:windows shell窗口
-1073741510
>>> os.system('calc') ?#運行系統的shell命令:calc計算器
0
>>> os.curdir ?#當前目錄('.')
'.'
>>> os.listdir(os.curdir) ?# 等同于 os.listdir('.')
['$RECYCLE.BIN', '.cache', '360Downloads', 'A', 'Jan_mi', 'Jan個人總資料', 'Qiyi', 'QQMusicCache', 'qycache', 'System Volume Information', 'Youku Files', 'Youxun', '博客']
>>> os.sep ?#輸出操作系統特定的路徑分隔符(Win下為'\\',Linux下為'/')
'\\'
>>> os.linesep ?#當前平臺使用的行終止符(Win下為'\r\n',Linux下為'\n')
'\r\n'
>>> os.name ?#指代當前使用的操作系統(包括:'posix', ?'nt', 'mac', 'os2', 'ce', 'java')
'nt' ?#nt是windows系統平臺


os.path 模塊(系統路徑模塊屬于os的子模塊)
>>> os.path.basename('E:\\A\\B\\C\\sexy.avi') ?#去掉目錄路徑,單獨返回文件名
'sexy.avi'
>>> os.path.dirname('E:\\A\\B\\C\\sexy.avi') ?#去掉文件名,單獨返回目錄路徑
'E:\\A\\B\\C'
>>> os.path.join('A', 'B', 'C') ?#將path1, path2...各部分組合成一個路徑名
'A\\B\\C'
>>> os.path.join('D:', 'A', 'B', 'C')
'D:A\\B\\C'
>>> os.path.join('D:\\', 'A', 'B', 'C') ?#注意盤符需要帶上斜杠
'D:\\A\\B\\C'
>>> os.path.split('E:\\A\\SEXY.AVI') ?#分割文件名與路徑,返回(f_path, f_name)元組。
('E:\\A', 'SEXY.AVI')
>>> os.path.split('E:\\A\\B\\C')
('E:\\A\\B', 'C')
>>> os.path.splitext('E:\\A\\SEXY.AVI') ?#分離文件名與擴展名,返回(f_name, f_extension)元組
('E:\\A\\SEXY', '.AVI')
>>> os.path.getatime('E:\\A\\test.txt') ?#返回指定文件最近的訪問時間
1504103243.229383 ?#浮點型秒數,可用time模塊的gmtime()或localtime()函數換算
>>> import time
>>> time.gmtime(os.path.getatime('E:\\A\\test.txt'))
time.struct_time(tm_year=2017, tm_mon=8, tm_mday=30, tm_hour=14, tm_min=27, tm_sec=23, tm_wday=2, tm_yday=242, tm_isdst=0)
>>> time.localtime(os.path.getatime('E:\\A\\test.txt'))
time.struct_time(tm_year=2017, tm_mon=8, tm_mday=30, tm_hour=22, tm_min=27, tm_sec=23, tm_wday=2, tm_yday=242, tm_isdst=0)
>>> time.localtime(os.path.getmtime('E:\\A\\test.txt'))
time.struct_time(tm_year=2017, tm_mon=8, tm_mday=30, tm_hour=22, tm_min=30, tm_sec=1, tm_wday=2, tm_yday=242, tm_isdst=0)
>>> time.localtime(os.path.getctime('E:\\A\\test.txt'))
time.struct_time(tm_year=2017, tm_mon=8, tm_mday=30, tm_hour=22, tm_min=27, tm_sec=23, tm_wday=2, tm_yday=242, tm_isdst=0)
>>> os.path.ismount('E:\\') ?#判斷指定路徑是否存在且是一個掛載點
True
>>> os.path.ismount('E:\\A')
False


pickle 模塊(泡菜模塊)
舉例:
>>> import pickle
>>> my_list = [123, 3.14, '名字', ['another list']]
>>> pickle_f = open('E:\\A\\my_list.pkl', 'wb')
>>> pickle.dump(my_list, pickle_f) ?#將list的內容傾倒入文件流對象中
>>> pickle_f.close()
>>> pickle_f = open('E:\\A\\my_list.pkl', 'rb')
>>> my_list2 = pickle.load(pickle_f) ?#將.pkl文件的內容裝載到list中
>>> print(my_list2)
[123, 3.14, '名字', ['another list']]


>>> city = {'城市1':'000001', '城市2':'000002', '城市n':'999999'} ?#此字典映射有70k這么大
>>> import pickle
>>> pickle_f = open('E:\\A\\city.pkl', 'wb') ?#將70k的字典映射寫入文件
>>> pickle.dump(city, pickle_f)
>>> pickle_f.close()
>>> pickle_file = open('E:\\A\\city.pkl', 'rb') ?#使用字典的時候打開文件裝載即可
>>> city = pickle.load(pickle_file)
>>> print(city)
{'城市2': '000002', '城市n': '999999', '城市1': '000001'}


---------------------------------2017.08.31--------------------------------------
16丶異常 exception
異常匯總
AssertionError 斷言語句(assert)失敗<eg1>
AttributeError 嘗試訪問未知的對象屬性<eg2>
EOFError 用戶輸入文件末尾標志EOF(Ctrl+d)?
FloatingPointError 浮點計算錯誤?
GeneratorExit generator.close()方法被調用的時候?
ImportError 導入模塊失敗的時候?
IndexError 索引超出序列的范圍<eg3>
KeyError 字典中查找一個不存在的關鍵字<eg4>
KeyboardInterrupt 用戶輸入中斷鍵(Ctrl+c)?
MemoryError 內存溢出(可通過刪除對象釋放內存)?
NameError 嘗試訪問一個不存在的變量?
NotImplementedError 尚未實現的方法?
OSError 操作系統產生的異常(例如打開一個不存在的文件)?
OverflowError 數值運算超出最大限制?
ReferenceError 弱引用(weak reference)試圖訪問一個已經被垃圾回收機制回收了的對象?
RuntimeError 一般的運行時錯誤?
StopIteration 迭代器沒有更多的值?
SyntaxError Python的語法錯誤?
IndentationError 縮進錯誤?
TabError Tab和空格混合使用?
SystemError Python編譯器系統錯誤?
SystemExit Python編譯器進程被關閉?
TypeError 不同類型間的無效操作?
UnboundLocalError 訪問一個未初始化的本地變量(NameError的子類)?
UnicodeError Unicode相關的錯誤(ValueError的子類)?
UnicodeEncodeError Unicode編碼時的錯誤(UnicodeError的子類)?
UnicodeDecodeError Unicode解碼時的錯誤(UnicodeError的子類)?
UnicodeTranslateError Unicode轉換時的錯誤(UnicodeError的子類)?
ValueError 傳入無效的參數?
ZeroDivisionError 除數為零?


部分舉例:
>>> my_list = ['我是帥哥', '你是美女']
>>> assert len(my_list) > 0
>>> my_list.pop()
'你是美女'
>>> my_list.pop()
'我是帥哥'
>>> assert len(my_list) > 0
Traceback (most recent call last):
? File "<pyshell#856>", line 1, in <module>
? ? assert len(my_list) > 0
AssertionError #斷言語句(assert)失敗
>>> my_list.abcd
Traceback (most recent call last):
? File "<pyshell#857>", line 1, in <module>
? ? my_list.abcd
AttributeError: 'list' object has no attribute 'abcd'#嘗試訪問未知的對象屬性
>>> my_list = [1, 2, 3]
>>> my_list[3]
Traceback (most recent call last):
? File "<pyshell#859>", line 1, in <module>
? ? my_list[3]
IndexError: list index out of range #索引超出序列的范圍
>>> my_list[2]
3
>>> my_dict = {'one':1, 'two':2, 'three':3}
>>> my_dict['one']
1
>>> my_dict['four']
Traceback (most recent call last):
? File "<pyshell#863>", line 1, in <module>
? ? my_dict['four']
KeyError: 'four' #字典中查找一個不存在的關鍵字
>>> my_dict.get('four')
>>> #dict.get(...)方法比較安全合適


異常檢測與處理
(1) try語句一旦檢測出現異常,則剩下的其他代碼則不會執行
(2) raise Exception_name 主動引發一個自定義異常名字的異常,可定義異常描述


try:
#檢測范圍
except Exception[as reason]:
#出現異常(Exception)后的處理代碼
finally:
#無論如何都會被執行的代碼(收尾工作)


舉例:
try:
? ? f = open('我為什么是一個文件.txt')
? ? print(f.read())
? ? f.close()
except OSError:
? ? print('文件出錯啦T_T')
運行:
文件出錯啦T_T


try:
? ? f = open('我為什么是一個文件.txt')
? ? print(f.read())
? ? f.close()
except OSError as reason:
? ? print('文件出錯啦T_T\n錯誤的原因是:' + str(reason))
運行:
文件出錯啦T_T
錯誤的原因是:[Errno 2] No such file or directory: '我為什么是一個文件.txt'


try:
? ? sum = 1 + '1'
? ? f = open('我為什么是一個文件.txt')
? ? print(f.read())
? ? f.close()
except (OSError, TypeError): ?#多個異常同時捕獲
? ? print('出錯啦T_T')
運行:出錯啦T_T


try:
? ? f = open('我為什么是一個文件.txt', 'w')
? ? print(f.write('我存在了!')) ?#沒有finally時并不會寫入文件
? ? sum = 1 + '1'
? ? f.close()
except (OSError, TypeError):
? ? print('出錯啦T_T')
finally:
? ? f.close()
運行:
5
出錯啦T_T


>>> raise ZeroDivisionError('除數為0的異常')
Traceback (most recent call last):
? File "<pyshell#872>", line 1, in <module>
? ? raise ZeroDivisionError('除數為0的異常')
ZeroDivisionError: 除數為0的異常


17丶豐富的esle-簡潔的with
else


舉例:while-else / for-else
def showMaxFactor(num):
? ? count = num // 2
? ? while count > 1:
? ? ? ? if num % count == 0:
? ? ? ? ? ? print('%d最大的約數是%d' % (num, count))
? ? ? ? ? ? break
? ? ? ? count -= 1
? ? else: #while循環完沒有break就會執行else
? ? ? ? print('%d是素數!' % num)


num = int(input('請輸入一個數:'))
showMaxFactor(num)


舉例:try-else
try:
? ? print(int('123'))
except ValueError as reason:
? ? print('出錯啦:' + str(reason))
else:
? ? print('Good!沒有任何異常。')
運行:
123
Good!沒有任何異常。


with as


舉例:
try:
? ? with open('data.txt', 'w') as f: #比 f = open(...) 多了文件不使用時自動關閉功能
? ? for each_line in f:
? ? ? ? print(each_line)
except OSError as reason:
? ? print('出錯啦:' + str(reason))
#finally: ? ? ? #有了with就不需要finally去調用關閉,會自動關閉
# ? ?f.close() ?#如果文件data.txt不存在就試圖去關閉一個不存在的文件


18丶圖形用戶界面 EasyGui
EasyGui官網:http://easygui.sourceforge.net
中文的教學文檔:http://bbs.fishc.com/thread-46069-1-1.html (要看完并實操)
模塊庫:easygui-0.96.zip


安裝方法:
(1) 使用命令窗口切換到easygui-docs-0.96的目錄下
(2) 【Windows下】執行C:\Python33\python.exe setup.py install
> cd Desktop
> cd puthon_study\easygui-0.96
#然后修改C:\Program Files (x86)\python\python.exe為管理員權限:右鍵-兼容性-更改所有用戶的設置-以管理員身份運行此程序-確定
> "C:\Program Files (x86)\python\python.exe" setup.py install
#生成了文件模塊庫C:\Program Files (x86)\python\Lib\site-packages\easygui.py
> "C:\Program Files (x86)\python\python.exe" easygui.py
#easygui的演示程序
PS: 【Linux或Mac下】sudo /Library/Framworks/Python.framework/Versions/3.3/bin/python3.3 setup.py install


使用方法:
【遇到難題】import easygui 出錯~!!!
【解決辦法】
(1) 重裝python IDLE勾選添加python路徑,選擇目錄安裝到C:\python文件夾,如重裝則忽略(2),如此一來win-cmd下的python中sys.path和IDLE中的sys.path則一致了。
(2) 對比windows命令窗口中啟動python與IDLE中python的系統路徑,添加到IDLE即可。


windows中系統路徑:
C:\Users\Jan> "C:\Program Files (x86)\python\python.exe"
>>> import sys
>>> sys.path
['',?
'C:\\Program Files (x86)\\python\\python35.zip',?
'C:\\Program Files (x86)\\python\\DLLs',?
'C:\\Program Files (x86)\\python\\lib',?
'C:\\Program Files (x86)\\python',?
'C:\\Program Files (x86)\\python\\lib\\site-packages']


IDLE中系統路徑:
>>> import easygui as g
Traceback (most recent call last):
? File "<pyshell#0>", line 1, in <module>
? ? import easygui as g
ImportError: No module named 'easygui'
>>> import sys
>>> sys.path
['',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\Lib\\idlelib',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\DLLs',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\lib',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35',?
'C:\\Users\\Jan\\AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages']
>>> sys.path.append('C:\\Program Files (x86)\\python\\python35.zip')
>>> sys.path.append('C:\\Program Files (x86)\\python\\DLLs')
>>> sys.path.append('C:\\Program Files (x86)\\python\\lib')
>>> sys.path.append('C:\\Program Files (x86)\\python')
>>> sys.path.append('C:\\Program Files (x86)\\python\\lib\\site-packages')
>>> import easygui as g ?#import ... as ... 導入模塊的同時重定義模塊名字
>>> g.msgbox('嗨,python!')
'OK'
>>>?
# No error, success... 但每次重啟IDLE都需要將windows下的sys.path進行添加。


# 示例,gui界面文字小游戲
import easygui as g
import sys


while 1:
? ? ? ? g.msgbox("嗨,歡迎進入第一個界面小游戲^_^")


? ? ? ? msg ="請問你希望在魚C工作室學習到什么知識呢?"
? ? ? ? title = "小游戲互動"
? ? ? ? choices = ["談戀愛", "編程", "OOXX", "琴棋書畫"]
? ? ? ??
? ? ? ? choice = g.choicebox(msg, title, choices)


? ? ? ? # note that we convert choice to string, in case
? ? ? ? # the user cancelled the choice, and we got None.
? ? ? ? g.msgbox("你的選擇是: " + str(choice), "結果")


? ? ? ? msg = "你希望重新開始小游戲嗎?"
? ? ? ? title = "請選擇"
? ? ? ??
? ? ? ? if g.ccbox(msg, title): ? ? # show a Continue/Cancel dialog
? ? ? ? ? ? ? ? pass ?# user chose Continue
? ? ? ? else:
? ? ? ? ? ? ? ? sys.exit(0) ? ? # user chose Cancel


---------------------------------2017.09.01--------------------------------------
19丶類和對象 class and object
面向對象(Object Oriented)
(1) python約定類名以大寫字母開頭
(2) 面向對象特征:封裝(信息隱蔽)、繼承(子類共享父類公共內容)、多態(不同對象對同一方法響應不同的行動)


類的示例:
class Turtle:
#屬性
color = 'green'
weight = 60
legs = 2
shell = True
age = 26


#方法
def climb(self):
print('我正在學習...')
def run(self):
print('我正在奔跑...')


運行:
>>> tt = Turtle() ?#類Turtle的示例對象tt
>>> Turtle
<class '__main__.Turtle'>
>>> type(Turtle)
<class 'type'>
>>> type('abc')
<class 'str'>
>>> tt.climb()
我正在學習...
>>> tt.run()
我正在奔跑...


#封裝
>>> list1 = [2, 1, 7, 5, 3]
>>> list1.sort() ?#sort() 方法封裝在list1對象中
>>> list1
[1, 2, 3, 5, 7]
>>> list1.append(9) ?#append() 方法封裝在list1對象中
>>> list1
[1, 2, 3, 5, 7, 9]


#繼承
>>> class Mylist(list):
pass
>>> list2 = Mylist()
>>> list2.append(5) ?#list2可以使用append()方法,繼承了Mylist(list)中的list參數類
>>> list2.append(3)
>>> list2.append(7)
>>> list2
[5, 3, 7]
>>> list2.sort()
>>> list2
[3, 5, 7]


#多態
>>> class A:
def fun(self):
print('我是小A')
>>> class B:
def fun(self):
print('我是小B')
>>> a = A()
>>> b = B()
>>> a.fun() ?#不同對象對同一方法響應不同的行動
我是小A
>>> b.fun() ?#不同對象對同一方法響應不同的行動
我是小B


self
相當于C++的this指針(指向當前對象本身的地址),表明類自身
舉例:
>>> class Ball:
def setName(self, name): ?#默認self的寫法
self.name = name
def kick(self): ?#默認self的寫法
print('我叫%s, 該死的誰踢我...' % self.name)
>>> a = Ball()
>>> a.setName('球A')
>>> b = Ball()
>>> b.setName('球B')
>>> c = Ball()
>>> c.setName('土豆')
>>> a.kick()
我叫球A, 該死的誰踢我...
>>> c.kick()
我叫土豆, 該死的誰踢我...


魔法方法:__init__(self)
__init__(self, parma1, parma2, ...)
舉例:
>>> class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print('我叫%s,該死的,誰踢我!!' % self.name)
>>> b = Ball('土豆')
>>> b.kick()
我叫土豆,該死的,誰踢我!!
>>> a = Ball() ?#__init__默認設置了name,所以必須傳遞name實參,否則報錯
TypeError: __init__() missing 1 required positional argument: 'name'


公有和私有
name mangling 名字改變/名字重造
公有成員:默認創建的成員均為公有。
私有成員:
(1) 在變量或函數名前加上"_"兩個下劃線即可。
(2) python中類的私有均屬于偽私有,通過"對象._類_變量"的形式可以訪問私有成員
舉例:
>>> class Person:
__name = 'yuan.jiang'
>>> p = Person()
>>> p.name
AttributeError: 'Person' object has no attribute 'name'
>>> p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> class Person:
__name = 'yuan.jiang'
def getName(self):
return self.__name
>>> p = Person()
>>> p.getName()
'yuan.jiang'
>>> p._Person__name ?#python中類的私有屬于偽私有,此方式可訪問私有成員
'yuan.jiang'


繼承 inherit
class DerivedClassName(BaseClassName):
...
(1) 如果子類中定義于父類同名的成員時,則會自動覆蓋父類對應的方法或屬性
(2) 解決子類中__init()


舉例:
>>> class Parent:
def hello(self):
print('正在調用父類的方法...')
>>> class Child(Parent):
pass
>>> p = Parent()
>>> p.hello()
正在調用父類的方法...
>>> c = Child()
>>> c.hello()
正在調用父類的方法...
>>> class Child(Parent):
def hello(self):
print('正在調用子類的方法...')
>>> c = Child()
>>> c.hello()
正在調用子類的方法...
>>> p.hello()
正在調用父類的方法...


舉例:
import random as r
class Fish:
? ? def __init__(self):
? ? ? ? self.x = r.randint(0, 10)
? ? ? ? self.y = r.randint(0, 10)


? ? def move(self):
? ? ? ? self.x -= 1
? ? ? ? print('我的位置是:', self.x, self.y)


class Goldfish(Fish):
? ? pass
class Carpfish(Fish):
? ? pass
class Salmonfish(Fish):
? ? pass
class Sharkfish(Fish):
? ? def __init__(self): ?#重寫了__init__方法覆蓋了父類的__init__子類無法調用到self.x和self.y屬性成員,導致了子類無法訪問到父類的屬性或方法的問題
? ? ? ? self.hungry = True
? ? def eat(self):
? ? ? ? if self.hungry:
? ? ? ? ? ? print('吃貨的夢想就是天天有的吃^_^')
? ? ? ? ? ? self.hungry = False
? ? ? ? else:
? ? ? ? ? ? print('太撐了,吃不下了!')
運行:
>>> fish = Fish()
>>> fish.move()
我的位置是: 3 0
>>> fish.move()
我的位置是: 2 0
>>> goldfish = Goldfish()
>>> goldfish.move()
我的位置是: 4 9
>>> goldfish.move()
我的位置是: 3 9
>>> shark = Sharkfish()
>>> shark.eat()
吃貨的夢想就是天天有的吃^_^
>>> shark.eat()
太撐了,吃不下了!
>>> shark.move() ?#無法訪問到父類的__init__()方法中的x變量
AttributeError: 'Sharkfish' object has no attribute 'x'


--------------------------------2017.09.02----------------------------------------


覆蓋屬性或方法問題優化
問題:針對子類屬性或方法覆蓋父類屬性或方法的情況,導致子類無法訪問父類中被覆蓋的屬性
(1) 調用未綁定的父類的方法
(2) 使用super方法(推薦)
舉例:
def __init__(self):
Fish.__init__(self) ?#調用未綁定的父類的方法,相當于>>>Fish.__init__(Sharkfish)
self.hungry = True
運行:
>>> shark = Sharkfish()
>>> shark.move()
我的位置是: -1 2
>>> shark.move()
我的位置是: -2 2


舉例:
def __init__(self):
super().__init__() ?#使用super方法解決
self.hungry = True
運行:
>>> shark = Sharkfish()
>>> shark.move()
我的位置是: 8 3
>>> shark.move()
我的位置是: 7 3


多重繼承
class DerivedClassName(Base1, Base2, Base3, ...):
...
#建議少用,有可能會導致不可預見的bug(不可預見最麻煩)
>>> class Base1:
def fool(self):
print('我是fool,我為Base1代言...')
>>> class Base2:
def fool2(self):
print('我是fool2,我為Base2代言...')
>>> class C(Base1, Base2):
pass
>>> c = C()
>>> c.fool()
我是fool,我為Base1代言...
>>> c.fool2()
我是fool2,我為Base2代言...


組合
class Turtle:
? ? def __init__(self, x):
? ? ? ? self.num = x
class Fish:
? ? def __init__(self, x):
? ? ? ? self.num = x
class Pool:
? ? def __init__(self, x, y): ?#組合的方式嵌套class
? ? ? ? self.turtle = Turtle(x)
? ? ? ? self.fish ?= Fish(y)
? ? def print_num(self):
? ? ? ? print('水池里總共有烏龜 %d 只,小魚 %d 條!' % (self.turtle.num, self.fish.num))
運行:
>>> pool = Pool(1, 10)
>>> pool.print_num()
水池里總共有烏龜 1 只,小魚 10 條!


類、類對象、示例對象
類定義 ? ?C
類對象 ? ?C
實例對象 ?a ?b ?c
舉例:
>>> class C: ? #C, 既是類,也是類對象
count = 0
>>> a = C() ? ?#a,實例對象
>>> b = C() ? ?#b,實例對象
>>> c = C() ? ?#c,實例對象
>>> a.count
0
>>> b.count
0
>>> c.count
0
>>> c.count += 10
>>> c.count
10
>>> a.count
0
>>> b.count
0
>>> C.count ? ?#C,作為類對象
0
>>> C.count += 100 ? ?#C,作為類對象
>>> a.count
100
>>> b.count
100
>>> c.count
10


(1) 當屬性名與方法名沖突,會導致方法不能正常調用。
(2) 一般遵循規則:屬性名用英文名詞,方法名用英文動詞。
(3) python嚴格要求方法需要有實例才能被調用,即綁定的概念。


舉例:
>>> class C:
def x(self):
print('X-man!')
>>> c = C()
>>> c.x()
X-man!
>>> c.x = 1
>>> c.x
1
>>> c.x() ?#方法名字被屬性名字覆蓋,調用出錯
TypeError: 'int' object is not callable


>>> class BB:
def printBB():
print('no zuo no die.')



>>> BB.printBB()
no zuo no die.
>>> #沒有self,也沒有將類實例化
>>> bb = BB()
>>> bb.printBB()
Traceback (most recent call last):
? File "<pyshell#187>", line 1, in <module>
? ? bb.printBB()
TypeError: printBB() takes 0 positional arguments but 1 was given
>>> class CC:
def setXY(self, x, y):
self.x = x;
self.y = y



>>> class CC:
def setXY(self, x, y):
self.x = x
self.y = y
def printXY(self):
print(self.x, self.y)



>>> dd = CC()
>>> dd.__dict__
{} ?#返回空的字典類型
>>> CC.__dict__
mappingproxy({'printXY': <function CC.printXY at 0x0000020483176EA0>, '__doc__': None, '__dict__': <attribute '__dict__' of 'CC' objects>, 'setXY': <function CC.setXY at 0x0000020483176E18>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'CC' objects>}) ?#使用類對象顯示類的屬性詳情
>>> dd.setXY(4, 5)
>>> dd.__dict__
{'y': 5, 'x': 4} ?#將實例對象dd使用類的屬性詳情實例化了
>>> # setXY(self, x, y) <==> dd.setXY(dd, x, y)
>>> del CC
>>> ee = CC()
NameError: name 'CC' is not defined
>>> dd.printXY()
4 5 ?#類中定義的屬性是靜態的,類的實例對象中也會靜態存儲,所以實例對象dd正常存在。


類與對象的內置函數
issubclass
功能:測試一個類是否是另外一個類的子類
issubclass(class, classinfo)
(1) 一個類被認為是其自身的子類
(2) classinfo可以是類對象的元組,只要class屬于其中任何一個候選類的子類,則返回True
舉例:
>>> class A:
pass
>>> class B(A):
pass
>>> issubclass(B, A)
True
>>> issubclass(B, B)
True
>>> issubclass(B, object) ?#object是所有類的基類
True
>>> class C:
pass
>>> issubclass(B, C)


isinstance
功能:測試一個對象是否是一個類的實例對象
isinstance(object, classinfo)
(1) object為類的實例對象,如果不是類的實例對象,永遠返回False
(2) 如果第二個參數不是類或者由類對象組成的元組,會拋出一個TypeError異常
舉例:
>>> class A:
pass
>>> class B(A):
pass
>>> class C:
pass
>>> b1 = B()
>>> isinstance(b1, B)
True
>>> isinstance(b1, A)
True
>>> isinstance(b1, C)
False
>>> isinstance(b1, (A, B, C)) ?#b1對象是否在A/B/C里面,答案是True
True


hasattr
功能:測試一個對象里面是否有指定的屬性
hasattr(object, name)
(1) object 對象名, name 是屬性名(需要用引號引起來,否則報錯)


getattr
功能:返回對象指定的屬性值
getattr(object, name[, default])
(1) 如果屬性值不存在打印default,沒有default則拋出異常


setattr
功能:設置對象中指定屬性的值,如果屬性不存在則創建并賦值
setattr(object, name, value)


delattr
功能:刪除對象中指定的屬性,如果屬性不存在則拋出異常
delattr(object, name)


舉例:
>>> class C:
def __init__(self, x=0):
self.x = x
>>> c1 = C()
>>> hasattr(c1, 'x') ?#測試對象屬性是否存在
True
>>> hasattr(c1, x)\
NameError: name 'x' is not defined
>>> getattr(c1, 'x') ?#獲取對象屬性的值
0
>>> getattr(c1, 'y')
AttributeError: 'C' object has no attribute 'y'
>>> getattr(c1, 'y', '您所訪問的屬性不存在!') ?#設置default默認提示語
'您所訪問的屬性不存在!'
>>> setattr(c1, 'y', 100) ?#設置對象屬性的值
>>> getattr(c1, 'y')
100
>>> delattr(c1, 'y') ?#刪除對象屬性的值
>>> delattr(c1, 'y')
Traceback (most recent call last):
? File "<pyshell#264>", line 1, in <module>
? ? delattr(c1, 'y')
AttributeError: y


property
功能:設置一個定義好的屬性,通過對象屬性來設置對象屬性
property(fget=None, fset=None, fdel=None, doc=None)
(1) fget獲取屬性的方法, fset設置屬性的方法, fdel刪除屬性的方法
舉例:
>>> class C:
def __init__(self, size=10):
self.size = size
def getSize(self):
return self.size
def setSize(self, value):
self.size = value
def delSize(self):
del self.size
x = property(getSize, setSize, delSize)
>>> c1 = C()
>>> c1.getSize()
10
>>> c1.x
10
>>> c1.x = 18
>>> c1.x
18
>>> c1.getSize()
18
>>> c1.size
18
>>> del c1.x
>>> c1.size ? ?#x與size相當于相互引用關系,刪除其中一個另一個即不能訪問
AttributeError: 'C' object has no attribute 'size'


20丶魔法方法 magic methods
(1) 魔法方法總是被雙下劃綫包圍,如 __init__
(2) 魔法方法是面向對象的python的一切
(3) 魔法方法的魔力體現在能夠在適當的時候被調用


魔法方法匯總:http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


__init__(self[, ...])
功能:初始化類對象(根據需求決定是否增加屬性參數)
返回值: None
舉例:
>>> class Rectangle: #矩形類,需要長和寬,所以重寫__init__
def __init__(self, x, y):
self.x = x
self.y = y
def getPeri(self): ?#獲得周長
return (self.x + self.y) * 2
def getArea(self): ?#獲得面積
return self.x * self.y
>>> rect = Rectangle(3, 4)
>>> rect.getPeri()
14
>>> rect.getArea()
12


__new__(class[, ...])
功能:創建一個類對象
返回值:返回一個對象
(1) 在__init__方法之前被調用,屬于類創建時第一個被調用的方法
舉例:
>>> class CapStr(str): ?#繼承一個不可改變的類型str
def __new__(cls, string): ?#使用new將類型的功能進行轉換
string = string.upper()
return str.__new__(cls, string) ?#把重寫后的str中的new方法帶傳代餐返回
>>> a = CapStr("I love M.")
>>> a
'I LOVE M.'


__del__(self)
功能:對象將要被銷毀的時候,自動調用,屬于自動垃圾回收方法
注意:del x != x.__del__()
舉例:
>>> class C:
def __init__(self):
print('我是init方法,我被調用了!')
def __del__(self):
print('我是del方法,我被調用了!')
>>> c1 = C()
我是init方法,我被調用了!
>>> c2 = c1 ?#對象的賦值不會調用__init__
>>> c3 = c2
>>> del c3
>>> del c2
>>> del c1 ? #其他的賦值對象del時不會調用__del__ (c2和c3只是c1的一份拷貝)
我是del方法,我被調用了!


算術運算魔法方法
__add__(self, other) 加法:+
__sub__(self, other) 減法:-
__mul__(self, other) 乘法:*
__truediv__(self, other) 真除法:/
__floordiv__(self, other) 整數除法://
__mod__(self, other) 取模算法:%
__divmod__(self, other) divmod()調用時的行為
__pow__(self, other[, modulo]) power()調用或 ** 運算時的行為
__lshift__(self, other) 按位左移:<<
__rshift__(self, other) 按位右移:>>
__and__(self, other) 按位與:&
__xor__(self, other) 按位異或:^
__or__(self, other) 按位或:|
舉例:
>>> class New_int(int):
def __add__(self, other):
return int.__sub__(self, other)
def __sub__(self, other):
return int.__add__(self, other)
>>> a = New_int(3)
>>> b = New_int(5)
>>> a + b
-2
>>> a - b
8
>>> class Try_int(int):
def __add__(self, other):
return int(self) + int(other)
def __sub__(self, other):
return int(self) - int(other)
>>> a = Try_int(3)
>>> b = Try_int(5)
>>> a + b
8


類定制的計時器
(1) 定制一個計時器的類
(2) start和stop方法代表啟動計時和停止計時
(3) 假設計時器對象t1,print(t1)和直接調用t1均顯示結果
(4) 當計時器未啟動或已經停止計時,調用stop方法會給與溫馨的提示
(5) 兩個計時器對象可以進行相加:t1 + t2
需要的資源:
(1) 使用time模塊的localtime方法獲取時間
(2) __str__ 方法 __repr__ 方法可用來打印文字


time 模塊
詳解鏈接:http://bbs.fishc.com/forum.php?mod=viewthread&tid=51326&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


struct_time元組
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=12, tm_min=18, tm_sec=55, tm_wday=5, tm_yday=245, tm_isdst=0)


類定制計時器代碼:http://blog.csdn.net/sinat_36184075/article/details/77806778


屬性訪問
__getattribute__(self, name) #定義當該類的屬性被訪問時的行為
__getattr__(self, name) #定義當用戶試圖獲取一個不存在的屬性時的行為
__setattr__(self, name, value) #定義當一個屬性被設置(包括初始化)時的行為
__delattr__(self, name) #定義一個屬性被刪除時的行為
舉例:
>>> class C:
def __getattribute__(self, name):
print('getattribute')
return super().__getattribute__(name)
def __getattr__(self, name):
print('getattr')
def __setattr__(self, name, value):
print('setattr')
super().__setattr__(name, value)
def __delattr__(self, name):
print('delattr')
super().__delattr__(name)
>>> c = C()
>>> c.x
getattribute
getattr
>>> c.x = 1
setattr ?#初始化時自動調用setattr
>>> c.x
getattribute
1
>>> del c.x
delattr


舉例:屬性訪問時的嚴重問題,無限遞歸
class Rectangle: ?#矩形
? ? def __init__(self, width=0, height=0): ?#寬高不相等,長方形
? ? ? ? self.width = width
? ? ? ? self.height = height


? ? def __setattr__(self, name, value):
? ? ? ? if name == 'square': ?#寬高相等,正方形
? ? ? ? ? ? self.width = value
? ? ? ? ? ? self.height = value
? ? ? ? else:
? ? ? ? ? ? #self.name = value ? #會導致類無限遞歸自己
? ? ? ? ? ? super().__setattr__(name, value) ?#解決辦法①:super() 推薦。
? ? ? ? ? ? #self.__dict__[name] = value ? ? ?#解決辦法②:字典
? ? def getArea(self):
? ? ? ? return self.width * self.height


運行:
>>> r1 = Rectangle(4, 5)
>>> r1.getArea()
20
>>> r1.square = 10 ?#正方形
>>> r1.width
10
>>> r1.height
10
>>> r1.getArea()
100
>>> r1.__dict__ ?#以字典的形式查看類中的屬性和值
{'width': 10, 'height': 10}


--------------------------------2017.09.03----------------------------------------
描述符 decriptor
描述符就是將某種特殊類型的類的實例指派給另一個類的屬性。
__get__(self, instance, owner) ?#用于訪問屬性,返回屬性的值
__set__(self, instance, value) ?#將在屬性分配操作中調用,不反悔任何內容
__delete__(self, instance) ? ?#控制刪除操作,不返回任何內容
@self, 描述符類本身的類實例
@instance, 擁有者的類實例
@owner, 擁有者類本身
@value, 所賦的值
舉例:
>>> class MyDecriptor:
def __get__(self, instance, owner):
print('getting: ', self, instance, owner)
def __set__(self, instance, value):
print('setting: ', self, instance, value)
def __delete__(self, instance):
print('deleting: ', self, instance)
>>> class Test:
x = MyDecriptor()
>>> #MyDecriptor是x的描述符類
>>> test = Test() ? #實例化Test()類
>>> test.x
getting: ?<__main__.MyDecriptor object at 0x000002164DC31FD0> <__main__.Test object at 0x000002164DBB6F28> <class '__main__.Test'>
>>> test
<__main__.Test object at 0x000002164DBB6F28>
>>> test.x = 'X-man'
setting: ?<__main__.MyDecriptor object at 0x000002164DC31FD0> <__main__.Test object at 0x000002164DBB6F28> X-man
>>> del test.x
deleting: ?<__main__.MyDecriptor object at 0x000002164DC31FD0> <__main__.Test object at 0x000002164DBB6F28>


自定義的描述符
>>> class MyProperty:
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __get__(self, instance, owner):
return self.fget(instance) ?#instance擁有者的實例對象
def __set__(self, instance, value):
self.fset(instance, value)
def __delete__(self, instance):
self.fdel(instance)



>>> class C:
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)



>>> c = C()
>>> c.x = 'X-man'
>>> c.x
'X-man' ?#使用x影響_x的值
>>> c._x
'X-man'
>>> del c.x ?#刪除后,c.x和c._x都不存在


練習:溫度轉換
定義一個溫度類,然后定義兩個描述符類用于描述攝氏度和華氏度兩個屬性。
要求兩個屬性會自動進行轉換,也就是說可以給攝氏度這個屬性賦值,打印華氏度是自動轉換后的結果。
代碼:
class Celsius:
? ? def __init__(self, value = 26.0):
? ? ? ? self.value = float(value)


? ? def __get__(self, instance, owner):
? ? ? ? return self.value
? ? def __set__(self, instance, value):
? ? ? ? self.value = float(value)


class Fahrenheit:
? ? def __get__(self, instance, owner): ?#instance就是Temperature(屬性:cel, fah)
? ? ? ? return instance.cel * 1.8 + 32
? ? def __set__(self, instance, value):
? ? ? ? #instance.cel = ('%.1f' % ((float(value) - 32) / 1.8)) ?#控制精度方法1
? ? ? ? instance.cel = round((float(value) - 32) / 1.8, 1) ? ? ?#控制精度方法2


class Temperature:
? ? cel = Celsius() ?#攝氏度
? ? fah = Fahrenheit() ?#華氏度, fah在實例對象中被賦值時調用對應類的__set__
運行:
>>> temp = Temperature()
>>> temp.cel
26.0
>>> temp.cel = 30
>>> temp.fah
86.0
>>> temp.fah = 100
>>> temp.cel
37.8


定制序列(容器)
(1) 如果希望定制的容器不可變,只需要定義魔法方法__len__()和__getitem__()
(2) 如果希望定制的容器可變,需要定義__len__()和__getitem__()和__setitem__()和__delitem__()


魔法方法詳解:
http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


練習:
編寫一個不可改變的自定義列表,要求記錄列表中每個元素被訪問的次數。
class CountList:
? ? def __init__(self, *args): ?#*args, 參數數量可變
? ? ? ? self.values = [x for x in args]
? ? ? ? self.count = {}.fromkeys(range(len(self.values)), 0)


? ? def __len__(self):
? ? ? ? return len(self.values)


? ? def __getitem__(self, key):
? ? ? ? self.count[key] += 1
? ? ? ? return self.values[key]
運行:
>>> c1 = CountList(1, 3, 5, 7, 9)
>>> c2 = CountList(2, 4, 6, 7, 10)
>>> c1[1] ?#c1[1] == 3被訪問1次
3
>>> c2[1]
4
>>> c1[1] + c2[1] ?#c1[1] == 3被訪問2次
7
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
>>> c1[1] ?#c1[1] == 3被訪問3次
3
>>> c1.count
{0: 0, 1: 3, 2: 0, 3: 0, 4: 0}


迭代器 iter-next
iter
iter() 內置方法, 功能:返回一個迭代器對象
__iter__() 魔法方法


next
next() 內置方法
__next__() ?魔法方法


for循環迭代器:
>>> links = {'百度':'http://www.baidu.com', \
'谷歌':'http://www.google.com', \
'搜狗':'http://www.sougou.com', \
'騰訊':'http://www.qq.com'}
>>> for each in links:
print("%s -> %s" % (each, links[each]))
谷歌 -> http://www.google.com
搜狗 -> http://www.sougou.com
騰訊 -> http://www.qq.com
百度 -> http://www.baidu.com


iter迭代器:
>>> string = 'yuan.jiang'
>>> it = iter(string)
>>> while True:
try:
each = next(it)
except StopIteration:
break;
print(each, end=' ')
運行:
y u a n . j i a n g?


斐波那契數列迭代器
>>> class Fibs: ?#斐波那契數列
def __init__(self, n=10): ? ?#加一個參數n控制迭代范圍
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self ?#本身就是一個迭代器
def __next__(self):
self.a, self.b = self.b, self.a+self.b
if self.a > self.n:
raise StopIteration
return self.a
>>> fibs = Fibs()
>>> for each in fibs:
print(each, end=' ')
1 1 2 3 5 8
>>> fibs = Fibs(100)
>>> for each in fibs:
print(each, end=' ')
1 1 2 3 5 8 13 21 34 55 89


生成器 yield
(1) 生成器是一種特殊的迭代器,兼容next()內置方法
(2) 生成器模仿了協同程序
協同程序:可以運行的對立函數調用,函數可以暫停或掛起,并再需要的時候從程序離開的地方繼續活著重新開始。
舉例:
>>> def MyGen():
print('生成器被執行!')
yield 1
yield 2
>>> myg = MyGen()
>>> next(myg)
生成器被執行!
1
>>> next(myg)
2
>>> next(myg)
StopIteration
>>> for i in MyGen(): ?#for循環自動檢測迭代器的StopIteration異常
print(i)
生成器被執行!
1
2
>>> def fibs():
a = 0
b = 1
while True:
a, b = b, a+b
yield a
>>> for each in fibs():
if each > 100:
break
print(each, end=' ')
1 1 2 3 5 8 13 21 34 55 89?


列表推導式
>>> a = [i for i in range(100) if not (i % 2) and (i % 3)] ?#列表推導式
>>> a
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46, 50, 52, 56, 58, 62, 64, 68, 70, 74, 76, 80, 82, 86, 88, 92, 94, 98]
>>> b = {i:i % 2 == 0 for i in range(10)} ?#字典推導式(例子:小于10以內的偶數)
>>> b
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}
>>> c = {i for i in [1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 3, 2, 1]} ?#集合推導式(元素不重復)
>>> c
{1, 2, 3, 4, 5, 6, 7, 8}
#沒有字符串推導式,引號內的強制解釋為字符串
>>> e = (i for i in range(10)) ?#沒有元組推導式,()小括號生成的是生成器推導式
>>> e
<generator object <genexpr> at 0x00000261E200A7D8>
>>> next(e)
0
>>> next(e)
1
>>> for each in e:
print(each, end=' ')
2 3 4 5 6 7 8 9?
>>> sum(i for i in range(100) if i % 2)
2500


生成器擴展閱讀:
http://bbs.fishc.com/forum.php?mod=viewthread&tid=56023&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403


21丶模塊 module
容器 -> 數據的封裝
函數 -> 語句的封裝
類 ? -> 方法和屬性的封裝
模塊 -> 程序的封裝,其實就是.py的python程序
(1) import導入的.py模塊文件必須放在與python.exe同一目錄下,即可正確導入。
(2) 導入方法有三種:
① import 模塊名
② from 模塊名 import 函數名1, 函數名2, ... ?#不建議這樣用,可能會覆蓋系統函數
③ import 模塊名 as 新名字
舉例:
在python下新建test_module文件夾:C:\python\test_module
C:\python\test_module\TempeatureConversion.py
C:\python\test_module\calc.py
#TempeatureConversion.py
def c2f(cel):
? ? fah = cel * 1.8 + 32
? ? return fah


def f2c(fah):
? ? cel = round((fah - 32) / 1.8, 1)
? ? return cel


#calc.py
import TemperatureConversion as tc


print('32攝氏度 = %.1f華氏度' % tc.c2f(32))
print('99華氏度 = %.1f攝氏度' % tc.f2c(99))


運行calc.py:
=================== RESTART: C:\python\test_module\calc.py ===================
32攝氏度 = 89.6華氏度
99華氏度 = 37.2攝氏度
>>>?


__name__
if __name__ = '__main__': ?#決定是.py文件中的代碼是當前程序運行,還是導入到其他程序中作為模塊使用而運行
作用:限制為自身.py程序運行才執行的代碼區域


搜索路徑 path
(1) 最佳存放模塊的目錄:C:\\python\\lib\\site-packages
>>> import sys
>>> sys.path
['', 'C:\\python\\Lib\\idlelib', 'C:\\python\\python35.zip', 'C:\\python\\DLLs', 'C:\\python\\lib', 'C:\\python', 'C:\\python\\lib\\site-packages']
>>> sys.path.append('C:\\python\\test_module') ?#自定義的模塊目錄可以append進去
>>> sys.path
['', 'C:\\python\\Lib\\idlelib', 'C:\\python\\python35.zip', 'C:\\python\\DLLs', 'C:\\python\\lib', 'C:\\python', 'C:\\python\\lib\\site-packages', 'C:\\python\\test_module']
>>> import TemperatureConversion as temp
>>> temp.c2f(32)
89.6


包 package
(1) python目錄下創建一個文件夾,用于存放相關的模塊,文件夾的名字即包(package)的名字
(2) 在文件夾中創建一個 __init__.py 的模塊文件,內容可以為空
舉例:
C:\python\test_module\calc.py
C:\python\test_module\M1\TemperatureConversion.py ?#M1文件夾名,即為包名
C:\python\test_module\M1\__init__.py ?#告訴python運行時將其解釋為包
#calc.py中修改為:包名.模塊名
import M1.TemperatureConversion as tc
print('32攝氏度 = %.1f華氏度' % tc.c2f(32))
print('99華氏度 = %.1f攝氏度' % tc.f2c(99))


自帶電池:python標準庫
(1) 電池:python-IDLE 幫助文檔 F1
(2) 來自全球開發者貢獻的python模塊:https://pypi.python.org/pypi
#也可以自己寫模塊發布上去。
(3) PEP:python增強建議書,規范與定義python各種加強和延伸功能的技術規格,即參考標準
(4) PEP規范內容歷史:http://www.python.org/dev/peps
(5) IDLE中模塊信息查看:
>>> import timeit
>>> print(timeit.__doc__) ?#幫助文檔
>>> dir(timeit) ?#內置方法
>>> timeit.__all__ ?#__all__屬性是可供外界調用的類或接口函數
>>> timeit.__file__ ?#__file__屬性是顯示模塊源代碼在本地的位置(學習高手的代碼)
>>> help(timeit) ?#幫助文檔


timeit 模塊詳解
地址:http://bbs.fishc.com/thread-55593-1-1.html


22丶python實例:網絡爬蟲
python訪問網絡: urllib (是個包模塊)
URL一般格式:
protocol://hostname[:port]/path/[;parameters][?query]#fragment
URL三部分組成:
(1) 協議:http, https, ftp, file, ed2k...
(2) 域名/IP地址:如http默認端口號80
(3) 資源具體地址:如目錄或文件名


查看幫助文檔后發現urllib包有4個模塊:
urllib.request #for opening and reading URLs?
urllib.error #containing the exceptions raised by urllib.request?
urllib.parse #for parsing URLs?
urllib.robotparser #for parsing robots.txt files?
嘗鮮:
>>> import urllib.request
>>> response = urllib.request.urlopen('http://www.fishc.com')
>>> html = response.read()
>>> print(html)
b'\xef...\r\n</html>\r\n' ?#整個網頁的二進制文件以16進制顯示
>>> html = html.decode('utf-8') ?#按其編碼方式解碼
>>> print(html)
"""
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
</body>
</html>
"""


訪問網頁內容存儲本地
舉例:
import urllib.request as url_req


response = url_req.urlopen('http://placekitten.com/g/1920/1080')
cat_img = response.read()


with open('cat_1920_1080.jpg', 'wb') as f:
? ? f.write(cat_img)
運行:
會生成這個文件:C:\Users\Jan\Desktop\python_study\cat_1920_1080.jpg


實現POST請求 - 自動翻譯機
import urllib.request as url_req
import urllib.parse ? as url_prs
import json ?#json, 輕量級的數據交換格式


while True:
? ? content = input('請輸入需要翻譯的內容<.q退出>:')
? ? if content == '.q':
? ? ? ? break
? ? else:
? ? ? ? #注意url地址<有道翻譯>,按小甲魚視頻中的可能不對,需到網上查別人的
? ? ? ? url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com/'
? ? ? ? data = {} ? #字典類型


? ? ? ? data['type'] = 'AUTO'
? ? ? ? data['i'] = content
? ? ? ? data['doctype'] = 'json'
? ? ? ? data['xmlVersion'] = '1.8'
? ? ? ? data['keyfrom'] = 'fanyi.web'
? ? ? ? data['ue'] = 'UTF-8'
? ? ? ? data['action'] = 'FY_BY_CLICKBUTTON'
? ? ? ? data['typoResult'] = 'true'


? ? ? ? data = url_prs.urlencode(data).encode('utf-8')
? ? ? ? response = url_req.urlopen(url, data)
? ? ? ? html = response.read().decode('utf-8')
? ? ? ? target = json.loads(html)
? ? ? ? print('翻譯結果:%s' % (target['translateResult'][0][0]['tgt']))
#缺陷:能夠被識別為代碼訪問,而非瀏覽器,即非人類訪問
運行:
========= RESTART: C:\Users\Jan\Desktop\python_study\translation.py =========
請輸入需要翻譯的內容<.q退出>:生存,還是毀滅,這是一個問題
翻譯結果:To survive, or not to be, this is a problem
請輸入需要翻譯的內容<.q退出>:To be or not to be, it's a question.
翻譯結果:生存還是毀滅,這是一個問題。
請輸入需要翻譯的內容<.q退出>:.q
>>>?


修改header
(1) 通過Request的headers參數修改,字典形式
(2) 通過Request.add_header()方法修改
追加header模擬瀏覽器訪問:
import urllib.request as url_req
import urllib.parse ? as url_prs
import json ?#json, 輕量級的數據交換格式


while True:
? ? content = input('請輸入需要翻譯的內容<.q退出>:')
? ? if content == '.q':
? ? ? ? break
? ? else:
? ? ? ? #注意url地址,視頻中的可能不對需到網上查
? ? ? ? url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=http://www.youdao.com/'


? ? ? ? #header方法1:創建字典,請求中傳參
? ? ? ? '''
? ? ? ? head = {} ?#模擬瀏覽器訪問 Request Headers
? ? ? ? head['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
? ? ? ? '''
? ? ? ? data = {} ?#From data
? ? ? ? data['type'] = 'AUTO'
? ? ? ? data['i'] = content
? ? ? ? data['doctype'] = 'json'
? ? ? ? data['xmlVersion'] = '1.8'
? ? ? ? data['keyfrom'] = 'fanyi.web'
? ? ? ? data['ue'] = 'UTF-8'
? ? ? ? data['action'] = 'FY_BY_CLICKBUTTON'
? ? ? ? data['typoResult'] = 'true'
? ? ? ? data = url_prs.urlencode(data).encode('utf-8')


? ? ? ? '''req = url_req.Request(url, data, head) ?#調用請求的方法:data, head '''
? ? ? ? #header方法2:請求中追加header
? ? ? ? req = url_req.Request(url, data)
? ? ? ? req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36')


? ? ? ? response = url_req.urlopen(req)
? ? ? ? html = response.read().decode('utf-8')
? ? ? ? target = json.loads(html)
? ? ? ? print('翻譯結果:%s' % (target['translateResult'][0][0]['tgt']))
運行:
========= RESTART: C:\Users\Jan\Desktop\python_study\translation.py =========
請輸入需要翻譯的內容<.q退出>:生存,還是毀滅,這是一個問題
翻譯結果:To survive, or not to be, this is a problem
請輸入需要翻譯的內容<.q退出>:To be or not to be, it's a question.
翻譯結果:生存還是毀滅,這是一個問題。
請輸入需要翻譯的內容<.q退出>:.q
>>>?


代理
作用:讓爬蟲偽裝瀏覽器請求,讓http服務器不會認為是非人類訪問。
步驟:
(1) 參數是一個字典{'類型':'代理ip:端口號'}
proxy_support = urllib.request.ProxyHandler({})
(2) 定制、創建一個opener
opener = urllib.request.build_opener(proxy_support)
(3) 安裝opener
urllib.request.install_opener(opener)
(4) 調用opener
opener.open(url)
#或:urllib.request.urlopen(url)
代碼:
import urllib.request as url_req
import random


url = 'http://www.whatismyip.com.tw' ?#這個網站訪問它會顯示自己的ip地址


#待完善:抓取代理ip網站上的ip和端口,存入iplist
iplist = ['115.197.136.78:8118', '118.250.50.69:80', '183.133.81.57:8118', ?'113.77.240.236:9797', '139.129.166.68:3128'] ?#使用random隨機取ip


#網上查的免費代理ip網站:http://www.xicidaili.com/
proxy_support = url_req.ProxyHandler({'http':random.choice(iplist)})
opener = url_req.build_opener(proxy_support)


#headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
opener.addheaders = [('User-Agent', 'Chrome/55.0.2883.87')]
url_req.install_opener(opener)


#req = url_req.Request(url, headers=headers)
#response = url_req.urlopen(req)
response = url_req.urlopen(url)


html = response.read().decode('utf-8')
print(html)


補充:
Beautiful Soup 是用Python寫的一個HTML/XML的解析器,使用安裝python-IDLE時附帶的pip命令,直接在windows下執行:
C:\python> pip install bs4
#一鍵安裝搞定,python中測試能否導入成功
>>> from bs4 import BeautifulSoup
>>> #成功導入,失敗會報異常。


采集代理ip
import urllib.request as url_req
from bs4 import BeautifulSoup ?#此庫需要安裝:win-cmd執行"pip install bs4"即可
import random
import pprint as ppr


#這個網站訪問它會顯示自己的ip地址
display_ip_url = 'http://www.whatismyip.com.tw' ? #'http://ip.chinaz.com/getip.aspx'


#代理ip網站, http協議類型
proxy_ip_url = 'http://www.xicidaili.com/wt/'


header = {}
header['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'


def getProxyIp(): ?#獲取代理ip
? ? proxyip_list = []
? ? for i in range(1, 2):
? ? ? ? try:
? ? ? ? ? ? url = proxy_ip_url + str(i) ?#抓取前2頁
? ? ? ? ? ? req = url_req.Request(url, headers=header)
? ? ? ? ? ? res = url_req.urlopen(req).read()
? ? ? ? ? ? soup = BeautifulSoup(res, "html.parser") ?#BeautifulSoup(markup, “html.parser”) html解析器
? ? ? ? ? ? ips = soup.findAll('tr') ?#findAll()搜索解析器解析出來的html文檔樹
? ? ? ? ? ? for x in range(1, len(ips)):
? ? ? ? ? ? ? ? ip = ips[x]
? ? ? ? ? ? ? ? tds = ip.findAll('td') ?#ip和端口都在tr標簽中的td標簽中
? ? ? ? ? ? ? ? ip_tmp = tds[1].contents[0] + ':' + tds[2].contents[0]
? ? ? ? ? ? ? ? proxyip_list.append(ip_tmp) ?#追加到列表
? ? ? ? except:
? ? ? ? ? ? continue
? ? return proxyip_list


iplist = getProxyIp()
#print(iplist) ? #for test
ppr.pprint(iplist) ?#以更規范的格式顯示輸出結果


#第一步:ProxyHandler傳參
ip_port = random.choice(iplist)
proxy_support = url_req.ProxyHandler({'http':ip_port}) ?#從列表中隨機選擇代理ip和端口項
print('ip:port ? ?' + ip_port)
#第二步:opener創建
opener = url_req.build_opener(proxy_support)
#第三步:opener安裝
opener.addheaders = [('User-Agent', 'Chrome/55.0.2883.87')]
url_req.install_opener(opener)
#第四步:opener調用
#response = url_req.urlopen(display_ip_url)
response = opener.open(display_ip_url) ?


html = response.read().decode('utf-8')
print(html)


運行:
======== RESTART: C:\Users\Jan\Desktop\python_study\proxy_support.py ========
<!DOCTYPE HTML>
<html>
? <head>
? ...
? </head>
? <body>
? <h1>IP位址</h1>
? <span data-ip='183.56.177.130'><b style='font-size: 1.5em;'>183.56.177.130</b> ?</span>
? <span data-ip-country='CN'><i>CN</i></span>
? <h1>真實IP</h1>
? <span data-ip-real='113.110.143.94'><b style='font-size: 1.5em;'>113.110.143.94</b></span>
? <span data-ip-real-country='CN'><i>CN</i></span>
? <script type="application/json" id="ip-json">
{
"ip": "183.56.177.130",
"ip-country": "CN",
"ip-real": "113.110.143.94",
"ip-real-country": "CN"
}
? </script>
? ...
? </body>
</html>


--------------------------------2017.09.04----------------------------------------
urllib.request 返回響應后的內置方法
import urllib.request as url_req
req = url_req.Request('http://url')
res = url_req.urlopen(req) #打開一個鏈接,參數可以是一個字符串或者Request對象
res.geturl() #返回鏈接的字符串,即urlopen的字符串參數
res.info() #返回http響應數據包的頭headers, 輸出:print(res.info())
res.getcode() #返回http響應的狀態碼


舉例:
=============== RESTART: C:/Users/Jan/Desktop/download_cat.py ===============
>>> res.geturl()
'http://placekitten.com/g/500/600'
>>> res.info()
<http.client.HTTPMessage object at 0x0000022E09C006D8>
>>> res.headers
<http.client.HTTPMessage object at 0x0000022E09C006D8>
>>> print(res.info())
Date: Mon, 04 Sep 2017 13:11:21 GMT
Content-Type: image/jpeg
Content-Length: 26590
Connection: close
Set-Cookie: __cfduid=d8354310653b8846db674de048175187b1504530681; expires=Tue, 04-Sep-18 13:11:21 GMT; path=/; domain=.placekitten.com; HttpOnly
Accept-Ranges: bytes
X-Powered-By: PleskLin
Access-Control-Allow-Origin: *
Cache-Control: public
Expires: Thu, 31 Dec 2020 20:00:00 GMT
Server: cloudflare-nginx
CF-RAY: 399131b5435b6d4e-SJC
>>> res.getcode()
200


python爬蟲下載妹子圖
代碼:#代理ip不太穩定,免費代理很多時好時壞
import urllib.request
import os
import random
import pprint as ppr
from bs4 import BeautifulSoup


header = {}
header_key = 'User-Agent'
header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
header[header_key] = header_value


def get_proxy_ip(): ?#獲取代理ip
? ? proxyip_list = []
? ? proxy_ip_url = 'http://www.xicidaili.com/wt/'
? ? for i in range(1, 2):
? ? ? ? try:
? ? ? ? ? ? url = proxy_ip_url + str(i)
? ? ? ? ? ? req = urllib.request.Request(url, headers=header)
? ? ? ? ? ? res = urllib.request.urlopen(req).read()
? ? ? ? ? ? soup = BeautifulSoup(res, "html.parser")
? ? ? ? ? ? ips = soup.findAll('tr')
? ? ? ? ? ? for x in range(1, len(ips)):
? ? ? ? ? ? ? ? ip = ips[x]
? ? ? ? ? ? ? ? tds = ip.findAll('td')
? ? ? ? ? ? ? ? ip_tmp = tds[1].contents[0] + ':' + tds[2].contents[0]
? ? ? ? ? ? ? ? proxyip_list.append(ip_tmp)
? ? ? ? except:
? ? ? ? ? ? continue
? ? return proxyip_list


#打開url接口函數
def url_open(url):
? ? req = urllib.request.Request(url)
? ? req.add_header(header_key, header_value)
? ? '''
? ? #使用代理模擬真人訪問而不是代碼訪問
? ? iplist = get_proxy_ip()
? ? #ppr.pprint(iplist) ?#for test
? ? ip_port = random.choice(iplist)
? ? proxy_support = urllib.request.ProxyHandler({'http':ip_port})
? ? print('ip:port ? ?' + ip_port) ?#for test
? ? opener = urllib.request.build_opener(proxy_support)
? ? opener.addheaders = [('User-Agent', 'Chrome/55.0.2883.87')]
? ? urllib.request.install_opener(opener)
? ? '''
? ? res = urllib.request.urlopen(url)
? ? html = res.read()


? ? print(url)
? ? return html


def get_page(url):
? ? html = url_open(url).decode('utf-8')


? ? a = html.find('current-comment-page') + 23
? ? b = html.find(']', a) ?#從a位置開始找到一個]符號
? ? print (html[a:b]) ?#for test


? ? return html[a:b]


def find_imgs(url):
? ? html = url_open(url).decode('utf-8')
? ? img_addrs = []


? ? a = html.find('img src=') ?#找到 img src= 的位置


? ? while a != -1:
? ? ? ? b = html.find('.jpg', a, a+255) ? #找到從a位置開始,以 .jpg 結尾的地方
? ? ? ? if b != -1: ?#find找不到時返回-1
? ? ? ? ? ? img_addrs.append('http:' + html[a+9:b+4]) ?#圖片鏈接地址追加到列表中, 9=len('img src="'), 4=len('.jpg')
? ? ? ? else:
? ? ? ? ? ? b = a + 9
? ? ? ??
? ? ? ? a = html.find('img src=', b) ? ? ?#下一次循環所找的位置就是從b開始


? ? #for each in img_addrs:
? ? # ? ?print(each)


? ? return img_addrs


def save_imgs(folder, img_addrs):
? ? for each in img_addrs:
? ? ? ? filename = each.split('/')[-1] ?#split以/分割字符串,-1取最后一個元素
? ? ? ? with open(filename, 'wb') as f:
? ? ? ? ? ? img = url_open(each)
? ? ? ? ? ? f.write(img)


def download_mm(folder='mm_dir', pages=25):
? ? if os.path.exists(folder):
? ? ? ? os.chdir(folder)
? ? else:
? ? ? ? os.mkdir(folder)
? ? ? ? os.chdir(folder)


? ? url = 'http://jandan.net/ooxx/' ?#實際圖源來源于新浪服務器
? ? page_num = int(get_page(url)) ? ?#函數get_page()


? ? for i in range(pages):
? ? ? ? page_num -= i
? ? ? ? page_url = url + 'page-' + str(page_num) + '#comments'
? ? ? ? img_addrs = find_imgs(page_url) ?#函數find_imgs()
? ? ? ? save_imgs(folder, img_addrs)


if __name__ == '__main__':
? ? download_mm()


--------------------------------2017.09.05----------------------------------------
正則表達式
"我知道,可以使用正則表達式解決現在遇到的難題。"于是,現在他就有兩個問題了。
>>> import re
>>> re.search(r'Hello', 'I love you, Hello!~') ?#search()方法用于在字符串中搜索正則表達式模式第一次出現的位置
<_sre.SRE_Match object; span=(12, 17), match='Hello'> ?#第12-16個字符位置
>>> re.search(r'lo', 'hello')
<_sre.SRE_Match object; span=(3, 5), match='lo'>
>>> 'hello'.find('lo')
3
#.點號:匹配除了換行符的任何字符
>>> re.search(r'.', 'I love you, baidu.com!~')
<_sre.SRE_Match object; span=(0, 1), match='I'>
#匹配點號本身,使用\反斜杠轉義即可
>>> re.search(r'\.', 'I love you, baidu.com!~')
<_sre.SRE_Match object; span=(17, 18), match='.'>
#\d表示匹配一個0~9的數字
>>> re.search(r'\d', 'I love 123, baidu.com!~')
<_sre.SRE_Match object; span=(7, 8), match='1'>
>>> re.search(r'\d\d\d', 'I love 123, baidu.com!~')
<_sre.SRE_Match object; span=(7, 10), match='123'>
>>> re.search(r'\d\d\d.\d\d\d.\d\d\d.\d\d\d', '192.168.111.123:8080')
<_sre.SRE_Match object; span=(0, 15), match='192.168.111.123'>
>>> re.search(r'\d\d\d.\d\d\d.\d\d\d.\d\d\d', '192.168.1.1') #無法匹配,位數不同
#使用[]創建一個字符類
>>> re.search(r'[aeiou]', 'I love you, baidu.com!~')
<_sre.SRE_Match object; span=(3, 4), match='o'>
>>> re.search(r'[aeiouAEIOU]', 'I love you, baidu.com!~')
<_sre.SRE_Match object; span=(0, 1), match='I'>
#-短杠:表示匹配的范圍
>>> re.search(r'[a-z]', 'I love you, baidu.com!~')
<_sre.SRE_Match object; span=(2, 3), match='l'>
>>> re.search(r'[0-9]', 'I love 123, baidu.com!~')
<_sre.SRE_Match object; span=(7, 8), match='1'>
#{}大括號:來限定匹配的次數
>>> re.search(r'ab{3}c', 'zabbbcz')
<_sre.SRE_Match object; span=(1, 6), match='abbbc'>
#{}3,10代表3到10次重復次數,不能有空格出現
>>> re.search(r'ab{3, 10}c', 'zabbbbbcz')
>>> re.search(r'ab{3,10}c', 'zabbbbbcz')
<_sre.SRE_Match object; span=(1, 8), match='abbbbbc'>
>>> re.search(r'[0-2][0-5][0-5]', '188') ?#錯誤示范
>>> re.search(r'[0-255]', '188') ?#0,1,2,5其中任何一個,匹配
<_sre.SRE_Match object; span=(0, 1), match='1'>
>>> re.search(r'[01]\d\d|2[0-4]\d|25[0-5]', '188') ?#0-255正則表達式
<_sre.SRE_Match object; span=(0, 3), match='188'>
#ip地址正則表達式
>>> re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])', '192.168.1.1')
<_sre.SRE_Match object; span=(0, 11), match='192.168.1.1'>
>>> re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])', '255.255.255.0')
<_sre.SRE_Match object; span=(0, 13), match='255.255.255.0'>
#此ip表達式的一點bug:
>>> re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])', '11192.168.41.8888')
<_sre.SRE_Match object; span=(2, 15), match='192.168.41.88'>


#ip地址匹配的正則表達式【嚴謹版】
import re
ptnIP = re.compile(r'(?<![\d.])' # 前導 無 數字和小數點
? ? ? ? ? ? ? ? ? ?r'(?:(?:'
? ? ? ? ? ? ? ? ? ?r'[01]?\d?\d' # ? 0 ~ 199
? ? ? ? ? ? ? ? ? ?r'|2[0-4]\d' ?# 200 ~ 249
? ? ? ? ? ? ? ? ? ?r'|25[0-5])' ?# 250 ~ 255
? ? ? ? ? ? ? ? ? ?r'\.){3}' ? ? # 3組 xxx.
? ? ? ? ? ? ? ? ? ?r'(?:'
? ? ? ? ? ? ? ? ? ?r'[01]?\d?\d'
? ? ? ? ? ? ? ? ? ?r'|2[0-4]\d'
? ? ? ? ? ? ? ? ? ?r'|25[0-5])'
? ? ? ? ? ? ? ? ? ?r'(?![\d.])' ?# 后續 無 數字和小數點
? ? ? ? ? ? ? ? ? )
test_IP = (
? ? ? ? '0.0.0.0'
? ? ? ? ';1.22.333.444' ? ? ? ? #不合法
? ? ? ? ';2.0.0.256' ? ? ? ? ? ?#不合法
? ? ? ? ';3.22.33.23333333' ? ? #不合法
? ? ? ? ';4.2.3.4.5' ? ? ? ? ? ?#不合法
? ? ? ? ';5.111.222.99'
? ? ? ? ';6.0.0.0'
? ? ? ? ';7.234.234.234'
? ? ? ? ';255.255.255.255'
? ? ? ? ';234.234.234.234'
? ? ? ? ';1192.168.41.888' ? ? ?#不合法
? ? ? ? )
match = ptnIP.findall(test_IP)
print(match)


運行:
========== RESTART: C:\Users\Jan\Desktop\python_study\ip_regular.py ==========
['0.0.0.0', '5.111.222.99', '6.0.0.0', '7.234.234.234', '255.255.255.255', '234.234.234.234'] ?#輸出均為合法ip


--------------------------------2017.09.07----------------------------------------
Python3 正則表達式特殊符號及用法(詳細列表)
http://blog.csdn.net/riba2534/article/details/54288552


正則表達式舉例:
import urllib.request
import re


header = {}
header_key = 'User-Agent'
header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
header[header_key] = header_value


def open_url(url):
? ? req = urllib.request.Request(url)
? ? req.add_header(header_key, header_value)
? ? page = urllib.request.urlopen(req)
? ? html = page.read().decode('utf-8')


? ? return html


def get_img(html):
? ? p = r'<img class="BDE_Image" src="([^"]+\.jpg)' ?# 正則表達式匹配貼吧圖片鏈接
? ? imglist = re.findall(p, html) ?# findall中的p包含子組()的話,會單獨返回子組


? ? # test start
? ? for each in imglist:
? ? ? ? print(each)
? ? # test end


? ? for each in imglist:
? ? ? ? filename = each.split("/")[-1]
? ? ? ? urllib.request.urlretrieve(each, filename, None)


if __name__ == '__main__':
? ? url = 'https://tieba.baidu.com/p/5310571187' ?# 下載百度貼吧圖片示例
? ? get_img(open_url(url))


運行:
https://imgsa.baidu.com/forum/w%3D580/sign=0b340d2849a7d933bfa8e47b9d4ad194/f1f8e3dde71190ef7241a5e3c51b9d16fcfa60a4.jpg
https://imgsa.baidu.com/forum/w%3D580/sign=6ff2514ff0f2b211e42e8546fa816511/fe4fbf014a90f6030c47ab7b3212b31bb151ed60.jpg
https://imgsa.baidu.com/forum/w%3D580/sign=7f8aadd5f9d3572c66e29cd4ba136352/b9dc748b4710b912bda70cc2c8fdfc03934522f1.jpg


優化采集代理ip:
import urllib.request
import re


header = {}
header_key = 'User-Agent'
header_value = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
header[header_key] = header_value


def open_url(url):
? ? req = urllib.request.Request(url)
? ? req.add_header(header_key, header_value)
? ? page = urllib.request.urlopen(req)
? ? html = page.read().decode('utf-8')


? ? return html


def get_ip(html):
? ? ptnIP = (r'(?<![\d.])' # 前導 無 數字和小數點
? ? ? ? ? ? ?r'(?:(?:'
? ? ? ? ? ? ?r'[01]?\d?\d' # ? 0 ~ 199
? ? ? ? ? ? ?r'|2[0-4]\d' ?# 200 ~ 249
? ? ? ? ? ? ?r'|25[0-5])' ?# 250 ~ 255
? ? ? ? ? ? ?r'\.){3}' ? ? # 3組 xxx.
? ? ? ? ? ? ?r'(?:'
? ? ? ? ? ? ?r'[01]?\d?\d'
? ? ? ? ? ? ?r'|2[0-4]\d'
? ? ? ? ? ? ?r'|25[0-5])'
? ? ? ? ? ? ?r'(?![\d.])') # 后續 無 數字和小數點
? ? iplist = re.findall(ptnIP, html) ?# findall中的p包含子組()的話,會單獨返回子組


? ? # test start
? ? for each in iplist:
? ? ? ? print(each)
? ? # test end


if __name__ == '__main__':
? ? url = 'http://www.xicidaili.com/wt/' ?# 下載代理ip
? ? get_ip(open_url(url))


異常處理
URLError 舉例:
>>> import urllib.request
>>> import urllib.error
>>> req = urllib.request.Request('http://www.ooxx-hello.com') ?#打開一個不存在的鏈接
>>> try:
urllib.request.urlopen(req)
except urllib.error.URLError as e:
print(e.reason)
[Errno 11001] getaddrinfo failed ?#錯誤信息


HTTPError 舉例:
>>> import urllib.request
>>> import urllib.error
>>> req = urllib.request.Request('http://www.fishC.com/ooxx.html')
>>> try:
urllib.request.urlopen(req)
except urllib.error.HTTPError as e:
print(e.code)
print(e.read())
404
b'<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL /ooxx.html was not found on this server.</p>\n<hr>\n<address>Apache Server at www.fishc.com Port 80</address>\n</body></html>\n'


處理異常的寫法:
from urllib.request import Request, urlopen
from urllib.error import URLError
req = Request('http://someurl/')
try:
response = urlopen(req)
except URLError as e:
if hasattr(e, 'reason'):
print('We failed to reach a server.')
print('Reason: ', e.reason)
elif hasattr(e, 'code'):
print('The server couldn\'t fulfill the request.')
print('Error code: ', e.code)
else:
#everything is fine.


--------------------------------2017.09.08----------------------------------------
Scrapy爬蟲框架


① Scrapy的安裝與環境搭建
Scrapy對應python2.7的版本。(安裝過程中如遇任何問題均可百度搜索一下,這是程序員必須學會的快速解決問題的辦法)
1. 安裝python2.7(32位版本)
安裝包:python-2.7.6-win32.msi
設置環境變量:win-運行-cmd
> C:\Python27\python.exe C:\Python27\tools\Scripts\win_add2path.py
重啟windows系統,驗證安裝是否成功:
> python --version
#如果顯示是3.多的版本,請參考python2/3版本切換任性切換設置:http://blog.csdn.net/sinat_36184075/article/details/77872708
2. 安裝pywin32(32位版本)
安裝包:pywin32-215.win32-py2.7.exe
3. 安裝python2.7的pip程序
安裝程序:get-pip.py
安裝方法:win-cmd> python C:\python\Scrapy\get-pip.py
先把pip的路徑添加到windows的環境變量中。
重啟windows系統,驗證安裝是否成功:
> pip --version
#如果沒有顯示版本信息,請參考pip2/3任性切換設置:http://blog.csdn.net/sinat_36184075/article/details/77872708
4. 安裝lxml
安裝環境包:VCForPython27.msi
> pip2 install lxml
#如果pip2的路徑有添加到windows中的話,安裝可以成功。如果不成功,使用下面安裝包安裝
安裝包:lxml-3.2.3.win32-py2.7.exe
5. 安裝OpenSSL
> pip2 install pyOpenSSL
#如果pip2的路徑有添加到windows中的話,安裝可以成功。如果不成功,使用下面安裝包安裝
安裝包:egenix-pyopenssl-0.13.7.win32-py2.7.msi
6. 安裝Scrapy
> pip2 install service_identity
> pip2 install Scrapy
驗證是否安裝成功:
> Scrapy
#如果提示找不到命令的話,可能需要一個工具環境支持:Twisted-15.0.0.win32-py2.7.msi
安裝完Twisted后再次嘗試驗證即可。




② Scrapy框架爬蟲程序初探
一個為了爬取網站數據,提取結構性數據而編寫的應用框架。最初是為了頁面抓取所設計的,也可以應用在獲取API所訪問的數據上,或者說通用的網絡爬蟲上。
使用Scrapy抓取一個網站一共需要四個步驟:
1. 創建一個Scrapy項目;
2. 定義Item容器;
3. 編寫爬蟲;
4. 存儲內容。


---Scrapy框架(官網)圖示---


實驗網站對象:www.dmoz.org


1. 創建一個Scrapy項目:crawler
C:\Users\Jan\Desktop\python_study>Scrapy startproject crawler
#crawler是我們的項目名稱
在\python_study\crawler\文件夾中即是我們的爬蟲框架。


Item是保存爬取到的數據的容器,其使用方法和python字典類似,并且提供了額外保護機制來避免拼寫錯誤導致的未定義字段錯誤。


2. 定義Item容器:
#crawler\crawler\items.py
import scrapy
class CrawlerItem(scrapy.Item):
? ? # define the fields for your item here like:
? ? # name = scrapy.Field()
? ? title = scrapy.Field()
? ? link = scrapy.Field()
? ? desc = scrapy.Field()


3. 編寫爬蟲:
編寫爬蟲類Spider,Spider是用戶編寫用于從網站上爬取數據的類。其包含了一個用于下載的初始化URL,然后是如何跟進網頁中的鏈接以及如何分析頁面中的內容,還有提取生成item的方法。
#crawler\crawler\spiders\crawler_spider.py 新建文件
import scrapy


class CrawlerSpider(scrapy.Spider):
? ? name = 'csdn' ?#爬蟲名字,調用的時候使用
? ? allowed_domains = ['csdn.net']
? ? start_urls = ['http://geek.csdn.net/AI']


? ? def parse(self, response):
? ? ? ? filename = response.url.split('/')[-2]
? ? ? ? with open(filename, 'wb') as f:
? ? ? ? ? ? f.write(response.body)
3.1 爬
win-cmd:
C:\Users\Jan\Desktop\python_study>cd crawler
C:\Users\Jan\Desktop\python_study\crawler>scrapy crawl csdn ?#csdn爬蟲類中的name
2017-09-08 21:56:28 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: crawler)
...
2017-09-08 21:56:30 [scrapy.core.engine] INFO: Spider opened
2017-09-08 21:56:30 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-09-08 21:56:30 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-09-08 21:56:30 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://geek.csdn.net/robots.txt> (referer: None) ?#Here: robots.txt
2017-09-08 21:56:30 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://geek.csdn.net/AI> (referer: None) ?#Here: 我們的目標爬取鏈接
2017-09-08 21:56:31 [scrapy.core.engine] INFO: Closing spider (finished)
...
2017-09-08 21:56:31 [scrapy.core.engine] INFO: Spider closed (finished)


#爬取的內容存儲位置(爬取網站的源碼文件):
C:\Users\Jan\Desktop\python_study\crawler\ 目錄下 geek.csdn.net 的NET文件。


3.2 取
在Scrapy中使用的是一種基于XPath和CSS的表達式機制:Scrapy Selectors(選擇器)
Selector是一個選擇器,有4個基本方法:
xpath() 傳入xpath表達式,返回該表達式所對應的所有節點的selector list列表。
css() 傳入CSS表達式,返回該表達式所對應的所有節點的selector list列表。
extract() 序列化該節點為unicode字符串并返回list。
re() 根據傳入的正則表達式對數據進行提取,返回unicode字符串list列表。


win-cmd進入項目根目錄后執行:scrapy shell "http://target_url/"
C:\Users\Jan\Desktop\python_study\crawler>scrapy shell "http://geek.csdn.net/AI"
2017-09-08 22:05:48 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: crawler)
...
2017-09-08 22:05:50 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-09-08 22:05:50 [scrapy.core.engine] INFO: Spider opened
2017-09-08 22:05:50 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://geek.csdn.net/robots.txt> (referer: None)
2017-09-08 22:05:50 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://geek.csdn.net/AI> (referer: None)
...
>>> response.body #輸出網頁的源碼信息
>>> response.headers ?#輸出網頁的頭部信息
{'Date': ['Fri, 08 Sep 2017 14:06:31 GMT'], 'Content-Type': ['text/html; charset=utf-8'], 'Server': ['openresty'], 'Vary': ['Accept-Encoding', 'Accept-Encoding']}


XPath是一門在網頁中查找特定信息的語言,所以用XPath來篩選數據,要比使用正則表達式容易些。
/html/head/title 選擇HTML文檔中<head>標簽內的<title>元素
/html/head/title/text() 選擇上面提到的<title>元素的文字
//td 選擇所有的<td>元素
//div[@class="mine"] 選擇所有具有 class="mine" 屬性的div元素


response.xpath() = response.selector.xpath() ?#已經映射。可以直接使用.xpath()
>>> response.xpath('//title')
[<Selector xpath='//title' data=u'<title>CSDN\u6781\u5ba2\u5934\u6761-\u63a8\u8350\u6bcf\u65e5\u6700\u65b0\u6700\u70edIT\u8d44\u8baf</title>'>] ?#\u的那些是中文字符,編碼方式決定顯示
>>> response.xpath('//title/text()').extract() ?#截圖title內容
[u'CSDN\u6781\u5ba2\u5934\u6761-\u63a8\u8350\u6bcf\u65e5\u6700\u65b0\u6700\u70edIT\u8d44\u8baf']
>>> sel.xpath('//span/a') ?#輸出所有<span><a>標簽的內容全部輸出
2017-09-08 22:36:08 [py.warnings] WARNING: <string>:1: ScrapyDeprecationWarning: "sel" shortcut is deprecated. Use "response.xpath()", "response.css()" or "response.selector" instead
>>> sel.xpath('//span/a/text()').extract() ?#獲取所有<span><a>標簽中的字符串,即標題
>>> sel.xpath('//span/a/@href').extract() ?#獲取<span><a>中的連接地址
>>> sites = sel.xpath('//div/div/div/dl/dd/span/a/text()').extract() ?#按照標簽包裹的層級<body>下開始找到包裹標題的<a>標簽寫入xpath中
>>> for title in sites: ?#使用for循環打印可以自動將Unicode轉換為對應中文編碼顯示
... ? ? print(title)
自己動手做聊天機器人 四十二-(重量級長文)從理論到實踐開發自己的聊天機器人
微軟攜手 Facebook 推出開源項目 打造共享神經網絡模型
Taylor Swift vs 人工智能:作詞誰更強?
推薦13個機器學習框架
...
>>> sites = sel.xpath('//div/div/div[@class="directory-url"]/dl/dd/span/a/text()').extract()
#其中[@class="directory-url"]的功能是:過濾掉對應樣式類的內容,此處僅做演示


#crawler\crawler\spiders\crawler_spider.py 修改代碼
import scrapy


class CrawlerSpider(scrapy.Spider):
? ? name = 'csdn'
? ? allowed_domains = ['csdn.net']
? ? start_urls = ['http://geek.csdn.net/AI']


? ? def parse(self, response):
? ? ? ? sel = scrapy.selector.Selector(response)
? ? ? ? sites = sel.xpath('//div/div/div/dl/dd/span')
? ? ? ? for site in sites:
? ? ? ? ? ? title = site.xpath('a/text()').extract()
? ? ? ? ? ? link ?= site.xpath('a/@href').extract()
? ? ? ? ? ? desc ?= site.xpath('text()').extract()
? ? ? ? ? ? print(title, link, desc)
win-cmd:
C:\Users\Jan\Desktop\python_study\crawler>scrapy crawl csdn
#運行就可以將print中的內容在爬取時一并顯示出來(輸出內容略)


4. 存儲內容
最常見的導出為json格式。
中文亂碼問題:http://bbs.fishc.com/thread-85672-1-1.html
#crawler\crawler\spiders\crawler_spider.py ?構造items的列表對象
import scrapy
from crawler.items import CrawlerItem


class CrawlerSpider(scrapy.Spider):
? ? name = 'csdn'
? ? allowed_domains = ['csdn.net']
? ? start_urls = ['http://geek.csdn.net/AI']


? ? def parse(self, response):
? ? ? ? sel = scrapy.selector.Selector(response)
? ? ? ? items = []
? ? ? ? sites = sel.xpath('//div/div/div/dl/dd/span')
? ? ? ? for site in sites:
? ? ? ? ? ? item = CrawlerItem() ?#實例化一個item類(類似于字典)
? ? ? ? ? ? item['title'] = site.xpath('a/text()').extract()
? ? ? ? ? ? item['link'] ?= site.xpath('a/@href').extract()
? ? ? ? ? ? item['desc'] ?= site.xpath('text()').extract()
? ? ? ? ? ? print(item['title'], item['link'], item['desc'])
? ? ? ? ? ? items.append(item)


? ? ? ? return items


#crawler\crawler\pipelines.py ?設置抓取內容存儲的文件名以及校正中文亂碼
import json
import codecs


store_filename = 'items.json' ? ?#item.json指的是要保存的json格式文件的名稱


class CrawlerPipeline(object):
? ? def __init__(self):
? ? ? ? self.file = codecs.open(store_filename, 'wb', encoding='utf-8') ?#中文編碼格式一般都是'utf-8'
? ? def process_item(self, item, spider):
? ? ? ? line = json.dumps(dict(item), ensure_ascii=False) + '\n' ?#這一句會將你每次返回的字典抓取出來,“ensure_ascii=False”這一句話很重要,如果是True的話就是我們保存的\u4e2d\u56fd這種格式了
? ? ? ? self.file.write(line) ?#寫入到文件中
? ? ? ? return item


#crawler\crawler\setting.py ?使pipelines.py生效,取消注釋ITEM_PIPELINES
ITEM_PIPELINES = {
? ? 'crawler.pipelines.CrawlerPipeline': 300, ?#300是正常值,不變。
}


win-cmd運行scrapy,即可自動在\crawler\目錄下生成items.json文件,并且中文顯示正常:
C:\Users\Jan\Desktop\python_study\crawler>scrapy crawl csdn
C:\Users\Jan\Desktop\python_study\crawler\items.json ?#中文正常。
{"title": ["自己動手做聊天機器人 四十二-(重量級長文)從理論到實踐開發自己的聊天機器人"], "link": ["http://www.shareditor.com/blogshow?blogId=136&hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io"], "desc": ["\n ? ? ? ? ? ? ? ? ? ? ? ? ? ?", "\n ? ? ? ? ? ? ? ? ? ? ? ?"]}
{"title": ["微軟攜手 Facebook 推出開源項目 打造共享神經網絡模型"], "link": ["http://tech.163.com/17/0908/08/CTQ1403R00097U80.html"], "desc": ["\n ? ? ? ? ? ? ? ? ? ? ? ? ? ?", "\n ? ? ? ? ? ? ? ? ? ? ? ?"]}
{"title": ["Taylor Swift vs 人工智能:作詞誰更強?"], "link": ["http://dataquestion.com/taylor-vs-ai"], "desc": ["\n ? ? ? ? ? ? ? ? ? ? ? ? ? ?", "\n ? ? ? ? ? ? ? ? ? ? ? ?"]}
...


--------------------------------2017.09.09----------------------------------------
23丶GUI界面的終極選擇 Tkinter
Tkinter是python的默認GUI模塊庫。
示例1:主窗口及標題
import tkinter as tk


app = tk.Tk() ?#根窗口的實例(root窗口)
app.title('Tkinter root window') ?#根窗口標題


theLabel = tk.Label(app, text='我的第2個窗口程序!') ?#label組件及文字內容
theLabel.pack() ?#pack()用于自動調節組件的尺寸


app.mainloop() ?#窗口的主事件循環,必須的。


示例2:按鈕
import tkinter as tk


class APP:
? ? def __init__(self, master): ?#root 傳參賦值給master
? ? ? ? frame = tk.Frame(master) ?#frame 組件
? ? ? ? frame.pack(side=tk.LEFT, padx=10, pady=10)


? ? ? ? self.hi_there = tk.Button(frame, text='打招呼', bg='black', fg='white', command=self.say_hi) ?#Button按鈕, command中調用定義的方法
? ? ? ? self.hi_there.pack()


? ? def say_hi(self):
? ? ? ? print('臥槽,居然打了個招呼!~')


root = tk.Tk()
app = APP(root)


root.mainloop()


示例3:圖片
from tkinter import *


root = Tk()
textLabel = Label(root,
? ? ? ? ? ? ? ? ? text='請重試!\n您的操作不被允許!', ?#文字支持換行
? ? ? ? ? ? ? ? ? justify=LEFT, ?#左對齊
? ? ? ? ? ? ? ? ? padx=10, ?#左邊距10px
? ? ? ? ? ? ? ? ? pady=10) ?#右邊距10px?
textLabel.pack(side=LEFT)


#顯示圖片
photo = PhotoImage(file='tk_image.png')
imageLabel = Label(root, image=photo)
imageLabel.pack(side=RIGHT)


mainloop()


示例4:背景
from tkinter import *


root = Tk()


photo = PhotoImage(file='tk4_bg.png')
theLabel = Label(root,
? ? ? ? ? ? ? ? ?text='生存還是毀滅\n這是一個問題',
? ? ? ? ? ? ? ? ?justify=LEFT,
? ? ? ? ? ? ? ? ?image=photo,
? ? ? ? ? ? ? ? ?compound=CENTER,
? ? ? ? ? ? ? ? ?font=('華文隸書', 20),
? ? ? ? ? ? ? ? ?fg='blue')
theLabel.pack()


mainloop()


示例5:按鈕交互
from tkinter import *


def callback():
? ? var.set('吹吧你,我才不信呢!')


root = Tk()


frame1 = Frame(root)
frame2 = Frame(root)


var = StringVar()
var.set('請重試!\n您的操作不被允許!')
textLabel = Label(frame1,
? ? ? ? ? ? ? ? ? textvariable=var,
? ? ? ? ? ? ? ? ? justify=LEFT) ?#左對齊
textLabel.pack(side=LEFT)


#顯示圖片
photo = PhotoImage(file='tk_image.png')
imageLabel = Label(root, image=photo)
imageLabel.pack(side=RIGHT)


theButton = Button(frame2, text='我是超級管理員', command=callback)
theButton.pack()


frame1.pack(padx=10, pady=10)
frame2.pack(padx=10, pady=10)


mainloop()


示例6:選項按鈕
from tkinter import *


root = Tk()


v = IntVar()


c = Checkbutton(root, text='測試一下', variable=v) ?#v用來存放選中狀態
c.pack()


l = Label(root, textvariable=v)
l.pack() ?#未選中顯示為0,選中顯示1


mainloop()


示例7:多個方框選項
from tkinter import *


root = Tk()


GIRLS = ['西施', '貂蟬', '王昭君', '楊玉環']


v = ?[]
for girl in GIRLS:
? ? v.append(IntVar())
? ? b = Checkbutton(root, text=girl, variable=v[-1])
? ? b.pack(anchor=W) ?#設置對齊方位,東E南S西W北N


mainloop()


示例8:多個圓點選項 Radiobutton
from tkinter import *


root = Tk()


v = IntVar()


Radiobutton(root, text='one', variable=v, value=1).pack(anchor=W)
Radiobutton(root, text='two', variable=v, value=2).pack(anchor=W)
Radiobutton(root, text='three', variable=v, value=3).pack(anchor=W)
Radiobutton(root, text='four', variable=v, value=4).pack(anchor=W)


mainloop()


示例9:內陷填充按鈕選項 Radiobutton indicatoron
from tkinter import *


root = Tk()


LANGS = [
? ? ('C', 1),
? ? ('C++', 2),
? ? ('shell', 3),
? ? ('python', 4)]


v = IntVar()
v.set(1)


for lang, num in LANGS: ?#對應列表中包含元組同時執行多個循環
? ? b = Radiobutton(root, text=lang, variable=v, value=num, indicatoron=False)
? ? b.pack(fill=X)


mainloop()


示例10:附帶標題的圓點選項 LabelFrame
from tkinter import *


root = Tk()


group = LabelFrame(root, text='最好的開發語言是?', padx=5, pady=5)
group.pack(padx=10, pady=10)


LANGS = [
? ? ('C', 1),
? ? ('C++', 2),
? ? ('shell', 3),
? ? ('python', 4)]


v = IntVar()
v.set(1)


for lang, num in LANGS: ?#對應列表中包含元組同時執行多個循環
? ? b = Radiobutton(group, text=lang, variable=v, value=num)
? ? b.pack(anchor=W)


mainloop()


示例11:輸入框 Entry
from tkinter import *


root = Tk()


e = Entry(root)
e.pack(padx=20, pady=20)


e.delete(0, END)
e.insert(0, '默認文本...')


mainloop()


示例12:按鈕和輸入框交互
from tkinter import *


root = Tk()
root.title('輸入框與按鈕程序')


Label(root, text='作品:').grid(row=0, column=0)
Label(root, text='作者:').grid(row=1, column=0)


e1 = Entry(root)
e2 = Entry(root)
e1.grid(row=0, column=1, padx=10, pady=5)
e2.grid(row=1, column=1, padx=10, pady=5)


def show(): ?#當輸入內容時點擊獲取信息會打印
? ? print('作品:《%s》' % e1.get())
? ? print('作者:《%s》' % e2.get())


Button(root, text='獲取信息', width=10, command=show) \
? ? ? ? ? ? ?.grid(row=3, column=0, sticky=W, padx=10, pady=5)
Button(root, text='點擊退出', width=10, command=root.quit) \
? ? ? ? ? ? ?.grid(row=3, column=1, sticky=E, padx=10, pady=5)
#退出按鈕必須是雙擊打開.py文件才可以,而不是在IDLE下調試運行時


mainloop()


示例12:登陸框程序
from tkinter import *


root = Tk()
root.title('登陸程序')


Label(root, text='賬號:').grid(row=0, column=0)
Label(root, text='密碼:').grid(row=1, column=0)


v1 = StringVar()
v2 = StringVar()


e1 = Entry(root, textvariable=v1)
e2 = Entry(root, textvariable=v2, show='*')
e1.grid(row=0, column=1, padx=10, pady=5)
e2.grid(row=1, column=1, padx=10, pady=5)


def show():
? ? print('賬號:%s' % e1.get())
? ? print('密碼:%s' % e2.get())


Button(root, text='芝麻開門', width=10, command=show) \
? ? ? ? ? ? ?.grid(row=3, column=0, sticky=W, padx=10, pady=5)
Button(root, text='點擊退出', width=10, command=root.quit) \
? ? ? ? ? ? ?.grid(row=3, column=1, sticky=E, padx=10, pady=5)
#退出按鈕必須是雙擊打開.py文件才可以,而不是在IDLE下調試運行時


mainloop()


示例13:輸入對錯驗證程序
from tkinter import *


root = Tk()
root.title('輸入對錯驗證')


def test():
? ? if e1.get() == '張三':
? ? ? ? print('正確!')
? ? ? ? return True
? ? else:
? ? ? ? print('錯誤!')
? ? ? ? e1.delete(0, END)
? ? ? ? return False


v = StringVar()


#focusout指定在當前輸入框失去焦點時,代表輸入完,會去調用test校驗<tab>鍵可測試
e1 = Entry(root, textvariable=v, validate='focusout', validatecommand=test)
e2 = Entry(root)
e1.pack(padx=10, pady=10)
e2.pack(padx=10, pady=10)


mainloop()


示例13:簡單計算器程序
from tkinter import *


root = Tk()
root.title('計算器程序')


frame = Frame(root)
frame.pack(padx=10, pady=10)


v1 = StringVar()
v2 = StringVar()
v3 = StringVar()


def test(content):
? ? return content.isdigit()


testCMD = frame.register(test)
#focusout指定在當前輸入框失去焦點時,代表輸入完,會去調用test校驗<tab>鍵可測試
e1 = Entry(frame, width=10, textvariable=v1, validate='key', \
? ? ? ? ? ?validatecommand=(testCMD, '%P')).grid(row=0, column=0) ?#width的單位是字符數
Label(frame, text='+').grid(row=0, column=1)


e2 = Entry(frame, width=10, textvariable=v2, validate='key', \
? ? ? ? ? ?validatecommand=(testCMD, '%P')).grid(row=0, column=2)
Label(frame, text='=').grid(row=0, column=3)


e3 = Entry(frame, width=10, textvariable=v3, state='readonly').grid(row=0, column=4)


def calc():
? ? result = int(v1.get()) + int(v2.get())
? ? v3.set(str(result))


Button(frame, text='計算結果', command=calc).grid(row=1, column=2, pady=5)


mainloop()


示例14:按鈕刪除列表中的選項
from tkinter import *


master= Tk()


theLB = Listbox(master, selectmode=SINGLE, height=15) ?#SINGLE單選,MULTIPLE多選,height設置顯示項數
theLB.pack()


for item in ['筆', '墨', '紙', '硯']:
? ? theLB.insert(END, item) ?#END表示最后一個


for item in range(11):
? ? theLB.insert(END, item)
? ??


theButton = Button(master, text='刪除', \
? ? ? ? ? ? ? ? ? ?command=lambda x=theLB:x.delete(ACTIVE) ) #ACTIVE表示當前選中的值
theButton.pack()


mainloop()


示例15:為列表組件添加滾動條
安裝垂直滾動條步驟:
1) 設置該組件的yscrollbarcommand選項為Scrollbar組件的set方法;
2) 設置Scrollbar組件的command選項為該組件的yview()方法。
from tkinter import *


root = Tk()
root.title('滾動條程序')


sb = Scrollbar(root)
sb.pack(side=RIGHT, fill=Y)


lb = Listbox(root, yscrollcommand=sb.set)


for i in range(1000):
? ? lb.insert(END, i)
lb.pack(side=LEFT, fill=BOTH)


#讓滾動條與選項互通互連
sb.config(command=lb.yview)


mainloop()


示例16:滑塊滾動條 Scale
from tkinter import *


root = Tk()
root.title('滑塊程序')


s1 = Scale(root, from_=0, to=100, tickinterval=5, resolution=5, length=200) ?#默認是垂直, tickinterval精度刻度, length單位是像素
s1.pack()


s2 = Scale(root, from_=0, to=100, tickinterval=5, orient=HORIZONTAL, length=400)
s2.pack()


def show():
? ? print(s1.get(), s2.get())


#獲取滑塊的當前位置,點擊后才有效
Button(root, text='音量:', command=show).pack()


mainloop()


示例17:文本組件 Text ?(插入按鈕)
from tkinter import *


root = Tk()
root.title('Text')


text = Text(root, width=30, height=20)
text.pack()


#窗口中的文本可編輯
text.insert(INSERT, '這里是顯示的文本信息內容。\n') ?#INSERT表示輸入光標插入的位置
text.insert(END, '對比一下效果。')


def show():
? ? print('提交中...') ?#此行內容顯示在IDLE中


#插入一個Button組件
b1 = Button(text, text='提交', command=show)
text.window_create(INSERT, window=b1) ?#將b1插入


mainloop()


示例18:文本組件 Text ?(插入圖片)
from tkinter import *


root = Tk()
root.title('Text')


text = Text(root, width=100, height=30)
text.pack()


photo = PhotoImage(file="tk_image.png")
def show_img():
? ? text.image_create(END, image=photo)


#插入一個圖片
b1 = Button(text, text='插入圖片', command=show_img)
text.window_create(INSERT, window=b1) ?#將b1插入


mainloop()


示例19:文本組件 Text ?(Indexes:索引定位)
from tkinter import *


root = Tk()
root.title('Text')


text = Text(root, width=30, height=10)
text.pack()
text.insert(INSERT, 'I love baidu.com!')


text.tag_add('tag1', '1.7', '1.12', '1.14') ?#1.7~1.12 baidu ? 1.14 o
text.tag_add('tag2', '1.7', '1.12', '1.14')
text.tag_config('tag1', background='blue', foreground='yellow')
text.tag_config('tag2', foreground='red') ?#文字會以red為準


mainloop()


示例20:文本組件中可點擊連接
from tkinter import *
import webbrowser as wb


root = Tk()
root.title('GUI link show')


text = Text(root, width=30, height=5)
text.pack()


text.insert(INSERT, 'I love baidu.com!')
text.tag_add('link', '1.7', '1.16')
text.tag_config('link', foreground='blue', underline=True)


def show_arrow_cursor(event):
? ? text.config(cursor='arrow')


def show_xterm_cursor(event):
? ? text.config(cursor='xterm')


def click(event):
? ? wb.open('http://www.baidu.com')


#綁定事件
text.tag_bind('link', '<Enter>', show_arrow_cursor) ?#<Enter>鼠標進入
text.tag_bind('link', '<Leave>', show_xterm_cursor) ?#<Enter>鼠標離開
text.tag_bind('link', '<Button-1>', click) ?#<Enter>鼠標點擊


mainloop()


示例21:文本組件之MD5
from tkinter import *
import hashlib ?#用于獲取文件的MD5值,檢查內容是否有修改


root = Tk()
root.title('link click')


text = Text(root, width=50, height=10)
text.pack()


text.insert(INSERT, 'I love www.baidu.com')
contents = text.get('1.0', END)


def getSig(contents):
? ? m = hashlib.md5(contents.encode())
? ? return m.digest()


sig = getSig(contents)


def check():
? ? contents = text.get('1.0', END)
? ? if sig != getSig(contents):
? ? ? ? print('內容有修改,是否保存?')
? ? else:
? ? ? ? print('無任何修改!')


Button(root, text='檢查', command=check).pack()


mainloop()


示例22:文本組件之全文搜索
from tkinter import *


root = Tk()
root.title('link click')


text = Text(root, width=50, height=10)
text.pack()


text.insert(INSERT, 'I love www.baidu.com')


def getIndex(text, index):
? ? return tuple(map(int, str.split(text.index(index), '.')))


start = '1.0' ?#開頭的位置,第1行的第0個下標位置
while True:
? ? pos = text.search('o', start, stopindex=END) ?#查找文本中字符o的位置
? ? if not pos:
? ? ? ? break
? ? print('找到啦,位置是:', getIndex(text, pos))
? ? start = pos + '+1c' ?#'+1c'指向下一個字符


mainloop()


示例23:文本組件之撤銷操作
from tkinter import *


root = Tk()
root.title('link click')


text = Text(root, width=50, height=10, undo=True) ?#undo模式開啟
text.pack()


text.insert(INSERT, 'I love www.baidu.com')


def show():
? ? text.edit_undo()


Button(root, text='撤銷', command=show).pack() ?#多次撤銷會刪除文本組件內的內容


mainloop()


示例24:繪制組件 Canvas
from tkinter import *


root = Tk()
root.title('Canvas')


w = Canvas(root, width=500, height=300) ?#background='black' 改變背景色
w.pack()


#黃色的矩形
w.create_rectangle(50, 50, 450, 250, fill='yellow') ?#參數:左邊距, 上邊距, 寬, 高
#紅色的橫線
w.create_line(0, 300//2, 500, 300//2, fill='red')
#藍色的豎虛線
w.create_line(500//2, 0, 500//2, 300, fill='blue', dash=(4, 4)) ?#dash 虛線


mainloop()


示例25:繪制組件 Canvas (修改和刪除圖形)
from tkinter import *


root = Tk()
root.title('Canvas')


w = Canvas(root, width=500, height=300) ?#background='black' 改變背景色
w.pack()


rect1 = w.create_rectangle(50, 50, 450, 250, fill='yellow') ?#參數:左邊距, 上邊距, 寬, 高
line1 = w.create_line(0, 300//2, 500, 300//2, fill='red')
line2 = w.create_line(500//2, 0, 500//2, 300, fill='blue', dash=(4, 4)) ?#dash 虛線


w.coords(line1, 0, 25, 500, 25) ?#移動位置
w.itemconfig(rect1, fill='red')
w.delete(line2)


Button(root, text='刪除全部', command=(lambda x=ALL:w.delete(x))).pack()


mainloop()


示例26:繪制組件 Canvas (圖形正中心)
from tkinter import *


root = Tk()
root.title('Canvas')


w = Canvas(root, width=600, height=300)
w.pack()




line1 = w.create_line(0, 0, 600, 300, fill='green', width=3)
line1 = w.create_line(600, 0, 0, 300, fill='green', width=3)
rect1 = w.create_rectangle(60, 30, 540, 270, fill='green')
rect2 = w.create_rectangle(120, 60, 480, 240, fill='yellow')


w.create_text(300, 150, text='Hello, python!')


mainloop()


示例27:繪制組件 Canvas (橢圓和圓形)
from tkinter import *


root = Tk()
root.title('Canvas')


w = Canvas(root, width=600, height=300)
w.pack()


w.create_rectangle(60, 30, 540, 270, dash=(4, 4))
w.create_oval(60, 30, 540, 270, fill='pink') ?#橢圓是通過限定矩形的方式畫出來,圓形通過正方形
#w.create_oval(60, 30, 300, 270, fill='pink') ?#正方形對應正圓(60-300=30-270)
w.create_text(300, 150, text='wow~')


mainloop()


示例28:繪制組件 Canvas (五角星)
from tkinter import *
import math as m ?#用到sin和cos數學函數


root = Tk()
root.title('Canvas')


w = Canvas(root, width=600, height=300, background='red')
w.pack()


center_x = 300
center_y = 150
r = 150


points = [
? ? #左上點
? ? center_x - int(r * m.sin(2 * m.pi / 5)),
? ? center_y - int(r * m.cos(2 * m.pi / 5)),
? ? #右上點
? ? center_x + int(r * m.sin(2 * m.pi / 5)),
? ? center_y - int(r * m.cos(2 * m.pi / 5)),
? ? #左下點
? ? center_x - int(r * m.sin(m.pi / 5)),
? ? center_y + int(r * m.cos(m.pi / 5)),
? ? #頂點
? ? center_x,
? ? center_y - r,
? ? #右下點
? ? center_x + int(r * m.sin(m.pi / 5)),
? ? center_y + int(r * m.cos(m.pi / 5)),
? ? ]


w.create_polygon(points, outline='yellow', fill='yellow') ?#polygon多邊形


mainloop()


示例29:繪制組件 Canvas (自定義畫板)
#繪制一個極小的圓來代表一個點(tkinter本身不支持畫點)
from tkinter import *


root = Tk()
root.title('Canvas draw tool')


w = Canvas(root, width=400, height=200, background='white')
w.pack()


def paint(event):
? ? x1, y1 = (event.x - 1), (event.y - 1)
? ? x2, y2 = (event.x + 1), (event.y + 1)
? ? w.create_oval(x1, y1, x2, y2, fill='red')


w.bind('<B1-Motion>', paint) ?#<B1-Motion>綁定鼠標左鍵事件


Label(root, text='按住鼠標左鍵并移動,開始繪制吧!~~').pack(side=BOTTOM)


mainloop()


示例30:菜單組件 Menu (主菜單/下拉菜單/右鍵菜單/單多選菜單/按鈕菜單/選項菜單(列表))
from tkinter import *


root = Tk()
root.title('Main Menu Show')


def callback():
? ? print('你好~')


menubar = Menu(root)


#注冊菜單:文件(下拉菜單)
filemenu = Menu(menubar, tearoff=False) ?#來自主菜單,tearoff參數可讓菜單窗口分離
filemenu.add_command(label='新建', command=callback)
filemenu.add_command(label='打開...', command=callback)
filemenu.add_separator() ?#分割線
filemenu.add_command(label='保存', command=callback)
filemenu.add_separator() ?#分割線
filemenu.add_command(label='退出', command=root.quit)
menubar.add_cascade(label='文件(W)', menu=filemenu)


#主菜單:編輯(下拉菜單)
editmenu = Menu(menubar, tearoff=False) ?#來自主菜單
editmenu.add_command(label='撤銷', command=callback)
editmenu.add_command(label='重做', command=callback)
editmenu.add_separator() ?#分割線
editmenu.add_command(label='剪切', command=callback)
editmenu.add_command(label='復制', command=callback)
editmenu.add_command(label='粘貼', command=callback)
editmenu.add_separator() ?#分割線
editmenu.add_command(label='全選', command=callback)
editmenu.add_separator() ?#分割線
editmenu.add_command(label='查找...', command=callback)
menubar.add_cascade(label='編輯(B)', menu=editmenu)


#主菜單:多選√ checkbutton(下拉菜單)
openVar = IntVar()
saveVar = IntVar()
quitVar = IntVar()
optionmenu = Menu(menubar, tearoff=False)
optionmenu.add_checkbutton(label='多選項1', command=callback, variable=openVar)
optionmenu.add_checkbutton(label='多選項2', command=callback, variable=saveVar)
optionmenu.add_checkbutton(label='多選項3', command=callback, variable=quitVar)
menubar.add_cascade(label='選項(C)', menu=optionmenu)


#主菜單:單選√ radiobutton(下拉菜單)
otherVar = IntVar()
othermenu = Menu(menubar, tearoff=False)
othermenu.add_radiobutton(label='單選項1', command=callback, variable=otherVar, value=1)
othermenu.add_radiobutton(label='單選項2', command=callback, variable=otherVar, value=2)
othermenu.add_radiobutton(label='單選項3', command=callback, variable=otherVar, value=3)
menubar.add_cascade(label='其他(C)', menu=othermenu)


#內部菜單:按鈕菜單 Menubutton
mb = Menubutton(root, text='按鈕菜單...', relief=RAISED)
mb.pack()
openVar = IntVar()
saveVar = IntVar()
quitVar = IntVar()
optionmenu = Menu(mb, tearoff=False)
optionmenu.add_checkbutton(label='test', command=callback, variable=openVar)
optionmenu.add_checkbutton(label='test', command=callback, variable=saveVar)
optionmenu.add_checkbutton(label='test', command=callback, variable=quitVar)
mb.config(menu=optionmenu)


#內部菜單:選項菜單 OptionMenu
variable = StringVar()
variable.set('one') ?#默認顯示one
w = OptionMenu(root, variable, 'one', 'two', 'three')
w.pack()


#將列表添加到選項菜單 OptionMenu
OPTIONS = [
? ? '表項1',
? ? '對比2',
? ? '選項3',
? ? '其他4',
? ? '退出5'
? ? ]
var = StringVar()
var.set(OPTIONS[0])
o = OptionMenu(root, var, *OPTIONS) ?#*星號解包可變參數列表為逐個元素
o.pack()


#主菜單:幫助
helpmenu = Menu(menubar, tearoff=False)
helpmenu.add_separator() ?#分割線
helpmenu.add_command(label='關于...', command=callback)
helpmenu.add_separator() ?#分割線
menubar.add_cascade(label='幫助(F1)', menu=helpmenu)


#彈出菜單(暫用編輯菜單作為右鍵)
frame = Frame(root, width=512, height=512)
frame.pack()
def popup(event):
? ? editmenu.post(event.x_root, event.y_root)
frame.bind('<Button-3>', popup) ?#Button-3為鼠標右鍵,1為左鍵,2為中鍵


root.config(menu=menubar) ?#menu參數會將菜單設置添加到root根窗口


mainloop()


示例31:事件綁定 bind (鼠標/按鍵/按鍵組合)
from tkinter import *


root = Tk()
root.title('Event bind')


frame = Frame(root, width=200, height=200)
#鼠標響應事件
def callback1(event): ?#event形參獲取事件描述,必備參數
? ? print('點擊位置:', event.x, event.y)
frame.bind('<Button-1>', callback1) ?#Button表示鼠標點擊事件, 12345分別代表左中右鍵上滾下滾
frame.pack()


#鍵盤響應事件
def callback2(event):
? ? print(event.keysym) ?#打印信息在IDLE, keysym指鍵盤所有按鍵
frame.bind('<Key>', callback2)
frame.focus_set()
frame.pack()


#鼠標即時響應事件
def callback3(event):
? ? print('點擊位置:', event.x, event.y)
frame.bind('<Motion>', callback3) ?#鼠標在窗口內只要有移動就一直輸出位置
frame.pack()


#事件序列(按鍵組合),語法:<modifier-type-detail> 如
#點擊鼠標左鍵:<Button-1> ?ButtonRelease更安全,移除組件釋放點擊時不去觸發
#點擊H字母按鍵:<KeyPress-H>
#同時點擊Ctrl+Shift+H:<Control-Shift-KeyPress-H>
mainloop()


示例32:消息組件 Message | 輸入組件 Spinbox
from tkinter import *


root = Tk()
root.title('Module')


#消息組件:Message
m1 = Message(root, text='這是一個消息:', width=100)
m1.pack()


m2 = Message(root, text='這是一\n則駭人聽聞的長長長長長長長消息!', width=100)
m2.pack()


#輸入組件:Spinbox ?(可指定輸入范圍)
s1 = Spinbox(root, from_=0, to=5)
s1.pack()
s2 = Spinbox(root, values=('zero', 'one', 'two', 'three', 'four', 'five'))
s2.pack()


mainloop()


示例33:窗口布局管理器 PanedWindow
from tkinter import *


root = Tk()
root.title('Module')


#二窗格
'''
p = PanedWindow(orient=VERTICAL)
p.pack(fill=BOTH, expand=1)


top = Label(p, text='top pane')
p.add(top)


bottom = Label(p, text='bottom pane')
p.add(bottom)
'''
#三窗格,同時顯示隱藏布局線(showhandle=True, sashrelief=SUNKEN)
p = PanedWindow(showhandle=True, sashrelief=SUNKEN)
p.pack(fill=BOTH, expand=1)


left = Label(p, text='left pane')
p.add(left)


q = PanedWindow(orient=VERTICAL, showhandle=True, sashrelief=SUNKEN)
p.add(q)


top = Label(q, text='top pane')
q.add(top)
bottom = Label(q, text='bottom pane')
q.add(bottom)


mainloop()


示例34:容器組件 Toplevel (創建頂級窗口,即彈出窗口)
from tkinter import *


root = Tk()
root.title('Toplevel')


def create():
? ? top = Toplevel()
? ? #top.attributes('-alpha', 0.5) 設置彈出的頂級窗口透明度:50%
? ? top.title('Toplevel demo...')


? ? msg = Message(top, text='I love python...')
? ? msg.pack()


Button(root, text='創建頂級窗口', command=create).pack() ?#點擊出現頂級窗口


mainloop()


示例35:幾何管理類,包pack(),網格grid(),位置place()
#pack() ?注意pack和grid不要混合使用
from tkinter import *


root = Tk()
root.title('pack')


#Listbox完全填充測試
listbox = Listbox(root)
listbox.pack(fill=BOTH, expand=True) ?#fill=BOTH將窗口填滿
for i in range(10):
? ? listbox.insert(END, str(i))


#Label縱向填充
Label(root, text='red', bg='red', fg='white').pack(fill=X)
Label(root, text='green', bg='green', fg='black').pack(fill=X)
Label(root, text='blue', bg='blue', fg='white').pack(fill=X)


#Label橫向填充
Label(root, text='red', bg='red', fg='white').pack(side=LEFT)
Label(root, text='green', bg='green', fg='black').pack(side=LEFT)
Label(root, text='blue', bg='blue', fg='white').pack(side=LEFT)


mainloop()


#grid() ?注意pack和grid不要混合使用
from tkinter import *


root = Tk()
root.title('grid')


#兩個sticky=W實現第一列左對齊
Label(root, text='用戶名').grid(row=0, sticky=W)
Label(root, text='密碼').grid(row=1, sticky=W)


#rowspan=2可以讓圖片橫跨2行
photo = PhotoImage(file='tk_image.png')
Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx=5, pady=5)


Entry(root).grid(row=0, column=1)
Entry(root, show='*').grid(row=1, column=1)


def callback():
? ? print('登陸中...')


#columnspan=3可以讓按鈕橫跨3列
Button(text='提交', width=10, command=callback).grid(row=2, columnspan=3, pady=5)


mainloop()


#place() ? 可以實現一些pack和grid實現不了的布局
from tkinter import *


root = Tk()
root.title('place')


#place位置布局測試
'''
photo = PhotoImage(file='tk_image.png')
Label(root, image=photo).pack() ?#按鈕就會出現在圖片的組件上,實現組件疊加顯示


def callback():
? ? print('正中靶心!!!')


#relx,rely相對父組件root的位置,0.5正中間,1最右邊,0最左邊,anchor=CENTER居中顯示
Button(root, text='射擊', command=callback).place(relx=0.5, rely=0.5, anchor=CENTER)
'''
Label(root, bg='red').place(relx=0.5, rely=0.5, relheight=0.75, relwidth=0.75, anchor=CENTER)
Label(root, bg='yellow').place(relx=0.5, rely=0.5, relheight=0.5, relwidth=0.5, anchor=CENTER)
Label(root, bg='blue').place(relx=0.5, rely=0.5, relheight=0.25, relwidth=0.25, anchor=CENTER)


mainloop()


示例35:對話框 (警告 showinfo | 消息 messagebox | 文件 filedialog | 顏色 colorchooser)
from tkinter import *
from tkinter import messagebox ? ?#messagebox()需要單獨導入
from tkinter import filedialog ? ?#filedialog()需要單獨導入
from tkinter import colorchooser ?#colorchooser()需要單獨導入
from tkinter.messagebox import * ?#用戶使用showinfo()


#警告對話框
showinfo(title='test', message='警告')


#消息對話框
result = messagebox.askokcancel('demo', '發射核彈?') ?#返回值是True或False
print(result) ?#根據用戶按下了確定還是取消做進一步的操作


#文件對話框
root = Tk()
def callback1():
? ? filename = filedialog.askopenfilename(defaultextension='.py') ?#指定文件后綴
? ? print(filename) ?#返回的是文件的完整路徑


Button(root, text='打開文件', command=callback1).pack()


#顏色選擇對話框
def callback2():
? ? color_data = colorchooser.askcolor() ?#調用windows的顏色選擇器
? ? print(color_data) ?#選擇紅色打印:((255.99609375, 0.0, 0.0), '#ff0000')


Button(root, text='選擇顏色', command=callback2).pack()


mainloop()





總結

以上是生活随笔為你收集整理的【python】速查手册(基础笔记) - 人生苦短,我用python的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

91在线视频观看 | 97av在线视频免费播放 | 九九热视频在线免费观看 | 亚洲精品麻豆视频 | 999久久久免费精品国产 | 国产最新在线视频 | 丁香婷婷色月天 | 久久三级视频 | 亚洲伊人婷婷 | 久艹视频在线免费观看 | 免费91麻豆精品国产自产在线观看 | 成人高清在线观看 | 亚洲一区久久 | 欧美视频日韩 | av最新资源 | 91在线国产观看 | 亚洲黄色在线播放 | 亚洲色图 校园春色 | 午夜精品视频免费在线观看 | 97视频久久久 | 欧美精品亚州精品 | 麻豆视频一区二区 | 激情欧美网 | 久久精品导航 | 久久综合给合久久狠狠色 | 国产精品视频在线看 | 亚洲欧美日韩中文在线 | 丰满少妇一级片 | 久草在线一免费新视频 | 免费视频黄 | 国产精品9999久久久久仙踪林 | 狠狠操电影网 | 亚洲人成人在线 | 免费在线观看中文字幕 | 色综合天天狠天天透天天伊人 | 一区二区三区www | 国产精品美女 | 久久99久久99精品免费看小说 | 97色婷婷成人综合在线观看 | 久久精品影片 | 色精品视频 | 97超碰在线视 | 狠狠精品 | 国产精品免费久久久久久久久久中文 | 夜夜操网| 91精品国自产在线观看 | 久久精品一区二区三区四区 | 免费a v在线 | 中文字幕亚洲不卡 | 婷婷亚洲综合 | 高清精品在线 | 美女福利视频在线 | 在线观看中文字幕网站 | 天天干人人干 | 日韩精品aaa | 久久亚洲精品电影 | 中文字幕在线一区二区三区 | 国产午夜三级一区二区三 | 久久免费在线观看视频 | 成人午夜电影免费在线观看 | 手机看片中文字幕 | 天天操天天操天天爽 | 麻豆91在线看 | 欧美aa一级片 | 久久久精品福利视频 | 97超碰伊人 | 久久久资源 | 五月婷婷爱| 国产精品免费久久久久久 | 久久久国产精品人人片99精片欧美一 | 免费看网站在线 | 丁香狠狠| 二区视频在线观看 | 婷婷丁香花五月天 | 在线亚洲日本 | 欧美色噜噜 | 久久精品导航 | 就操操久久 | 国产在线91精品 | 91九色在线观看视频 | 久久天堂影院 | 欧美在线视频不卡 | 午夜影院在线观看18 | 欧美久久久久久久久 | 欧美一区二区免费在线观看 | 欧美日韩精品免费观看 | 国产无遮挡又黄又爽馒头漫画 | 欧美成年人在线视频 | 午夜成人免费电影 | 91精品国产91久久久久福利 | 亚洲欧美综合精品久久成人 | 久久夜色电影 | 久久精品美女视频 | 亚洲精品视频在线观看免费视频 | 在线观看久久久久久 | 69国产成人综合久久精品欧美 | 黄色在线看网站 | 美女精品在线 | 中文字幕 国产视频 | 国产亚洲精品久久久久久无几年桃 | 亚洲人人射 | 中文字幕在线精品 | 日韩av播放在线 | 国产精品久久久久久久久软件 | 中文字幕成人在线 | 日韩一区二区三区免费视频 | 激情综合网五月激情 | 激情电影影院 | 婷婷伊人综合亚洲综合网 | 中文字幕在线看片 | 日韩电影中文,亚洲精品乱码 | 日韩一二区在线 | 玖玖在线看 | 亚洲天堂网视频 | 亚洲欧美国产精品久久久久 | 五月婷婷激情六月 | 日日夜夜天天 | 精品久久久久久国产偷窥 | 91麻豆网站 | av免费观看高清 | 在线免费观看涩涩 | 国产成人久久精品77777综合 | 国产精品 中文字幕 亚洲 欧美 | 狠狠色丁香久久婷婷综合丁香 | 最近中文字幕免费视频 | 香蕉网在线 | 玖玖在线资源 | 亚洲成年片 | 在线91色 | 日韩三级一区 | 久久精品久久精品 | 99视频国产在线 | 超碰在线99| 在线中文字幕av观看 | 视频在线观看国产 | 国产这里只有精品 | 在线观看国产www | 亚洲人天堂 | www.亚洲黄色 | 欧美成人理伦片 | 中文字幕在线观 | 人人插人人做 | 国产在线观看一 | 亚洲涩涩网站 | 亚洲免费在线观看视频 | 欧美综合在线视频 | 日本精品久久久久中文字幕 | 婷婷丁香国产 | 天天干天天操天天干 | 特黄特色特刺激视频免费播放 | 在线视频电影 | 亚洲国产精品久久久久婷婷884 | 日韩网站免费观看 | 黄网在线免费观看 | 这里只有精彩视频 | 国产精品一区二区三区在线免费观看 | 中文字字幕在线 | 毛片区 | 欧美国产不卡 | 久久久久看片 | 日韩高清一区 | 亚州激情视频 | 欧美另类性 | 国产成人性色生活片 | 91大片网站| 婷婷久草| 激情综合色综合久久 | a级国产片 | av大片免费在线观看 | 日韩区欧美久久久无人区 | 亚洲精品免费观看视频 | 国产一级黄色片免费看 | 一区二区三区动漫 | 99re6热在线精品视频 | 国产亚洲精品久久久网站好莱 | 亚洲狠狠婷婷 | 黄色网中文字幕 | 成人黄色片在线播放 | 欧美一级特黄aaaaaa大片在线观看 | 日韩av综合网站 | 久久激情综合网 | 国产亚洲免费的视频看 | 成人免费视频视频在线观看 免费 | 狠狠搞,com | 国产1区在线观看 | 天无日天天操天天干 | 国产区 在线 | 在线观看日韩专区 | 亚洲一区二区高潮无套美女 | 五月婷婷丁香在线观看 | 91福利视频在线 | 国产情侣一区 | 国产一区欧美日韩 | 久久精品国产一区 | 色狠狠久久av五月综合 | 日韩欧美69 | 91九色视频在线播放 | 99久久精品国产亚洲 | 操操操天天操 | 香蕉久久久久久久 | 久久网站最新地址 | 日本一区二区三区免费观看 | 99r国产精品 | 久久影院亚洲 | 亚州人成在线播放 | 中文字幕国产精品 | 日韩视频免费播放 | 日韩在线小视频 | 欧美精品亚州精品 | 亚洲一区二区三区四区精品 | 国内精品中文字幕 | 一区二区三区日韩精品 | 激情综合网天天干 | 国产日韩精品一区二区在线观看播放 | 丁香在线视频 | av中文字幕电影 | 日狠狠| 欧美日韩一区二区在线观看 | 特级免费毛片 | 午夜精品久久久久久久99 | 亚洲综合精品视频 | 亚洲视频免费在线观看 | 一本到在线 | 亚洲综合爱 | 九九视频热 | 久久看毛片 | 日韩精品欧美专区 | 五月婷婷久久丁香 | 亚洲欧美经典 | 国产精品一区二区久久久 | 成人91在线 | 天天夜夜亚洲 | 国产精品久久久久久69 | 2019精品手机国产品在线 | 日韩中文字幕在线不卡 | 91久久偷偷做嫩草影院 | 久久免费一| 九九九热精品免费视频观看网站 | 亚洲一区二区黄色 | 日本成人免费在线观看 | 国产一区视频在线 | 免费观看国产精品视频 | 91在线播放综合 | 啪啪激情网 | 久久久午夜精品理论片中文字幕 | 美女免费视频网站 | 亚洲精品在线看 | 亚州视频在线 | 人人澡人 | 国产精品v欧美精品v日韩 | 亚洲婷婷在线视频 | 婷婷四房综合激情五月 | japanesefreesexvideo高潮 | 国产999精品久久久久久绿帽 | 三级av中文字幕 | 涩涩在线 | 三上悠亚一区二区在线观看 | 日韩精品久久久免费观看夜色 | 精品国产伦一区二区三区观看方式 | a国产精品 | 亚洲欧美日韩国产精品一区午夜 | 免费h漫在线观看 | 在线观看精品视频 | 碰超在线 | 色噜噜在线观看 | 久久久久久久久亚洲精品 | 国产一区私人高清影院 | 天天草天天操 | 亚洲综合一区二区精品导航 | 久久久男人的天堂 | 亚洲精品中文在线 | 丁香婷婷亚洲 | 人人爽爽人人 | 欧美日韩不卡一区二区三区 | 最新av在线免费观看 | 日日夜夜婷婷 | 国产精品porn| 三级小视频在线观看 | 亚洲 欧美 另类人妖 | 久草免费手机视频 | 91黄色小视频 | 91精彩在线视频 | 精品不卡视频 | 亚洲另类视频在线 | 国产午夜精品久久 | 四虎成人精品永久免费av九九 | 黄色软件网站在线观看 | 久久久国产影视 | 中文字幕在线视频一区二区 | 成人av高清在线观看 | 日本三级在线观看中文字 | 久久综合之合合综合久久 | aaa免费毛片 | 热精品| 九九精品视频在线看 | 亚洲一区网站 | 免费久久久久久 | 美女福利视频一区二区 | 国产99久久久国产精品 | 国产中文字幕亚洲 | 综合网色 | av片一区 | 日韩av网址在线 | 欧美一区成人 | 久久久96| 91手机在线看片 | 免费观看成人 | 99r在线观看 | 免费在线观看av片 | 丁香婷婷深情五月亚洲 | 九九免费在线观看视频 | 国产日女人 | 国产成人精品女人久久久 | 日本护士三级少妇三级999 | 欧美色精品天天在线观看视频 | 精品国产伦一区二区三区观看方式 | 久久不卡免费视频 | 午夜av不卡 | 国产婷婷精品av在线 | av免费看网站 | 97电院网手机版 | 91免费国产在线观看 | 国产区欧美| 玖玖精品在线 | 91在线观看视频 | 99re8这里有精品热视频免费 | 欧美日韩精品网站 | 国产免费观看高清完整版 | www.天天射 | 一区二区av | 午夜精品麻豆 | 国产不卡在线播放 | 国产精品成人一区二区三区吃奶 | 日韩在线观看一区 | 亚洲精品高清视频 | 超碰人人超 | 久久精品—区二区三区 | 午夜精品99久久免费 | 亚洲一区二区三区毛片 | 国产精品毛片一区二区 | 欧美日韩中文视频 | 成人资源站 | 欧美特一级 | 91麻豆精品国产91久久久使用方法 | 91爱爱电影 | 4438全国亚洲精品在线观看视频 | www.亚洲| 久久亚洲福利视频 | 久久91网| 黄色一二级片 | 狠狠精品 | 99久久精品午夜一区二区小说 | 日本少妇久久久 | 最新91在线视频 | 国产精品99在线播放 | 91看片淫黄大片在线播放 | 激情开心色 | av成年人电影 | 人人爽人人澡人人添人人人人 | 亚洲视频六区 | 亚洲黄色在线播放 | 天天射射天天 | 欧美在线1区 | 日日日干 | 人人爽人人爽人人片av | 日韩av午夜 | 视频一区二区在线 | 欧美日韩高清在线一区 | 黄毛片在线观看 | 五月天综合网 | 久久精品国产成人 | 国产成人精品久久久 | 国产小视频在线观看免费 | 国内精品久久久久久久97牛牛 | 国产精品午夜免费福利视频 | 免费观看黄 | 久久五月婷婷综合 | 久久久久福利视频 | 五月天堂网 | 中文字幕一区二区三区视频 | 国产一区二区在线看 | 日韩成人精品在线观看 | 国产成人精品综合久久久 | 日韩av在线看 | 免费看十八岁美女 | 日本精a在线观看 | 久久久久北条麻妃免费看 | 成年免费在线视频 | 日韩av网址在线 | 激情欧美丁香 | 一级黄色av | 久久天天躁夜夜躁狠狠躁2022 | 亚洲精品在线二区 | 国产黄色成人av | 日韩中文字幕国产精品 | 天天草综合 | 99久久精品国产网站 | 久久国产一区 | 国产黄色成人av | 91麻豆免费视频 | 欧美性色xo影院 | 人人干天天射 | 亚洲精品一区二区三区高潮 | 在线看黄色av | 精品国精品自拍自在线 | 丝袜美女视频网站 | www.久草.com| 美女av免费| 日韩久久久久久久 | 成年人黄色大片在线 | 成人动态视频 | 国产手机视频 | 久久久鲁 | 日韩啪啪小视频 | 成人小视频在线免费观看 | 天天做天天爱夜夜爽 | 久久久久亚洲国产 | 国产日韩在线看 | www夜夜| 日本精品二区 | 激情综合五月婷婷 | 亚洲精品麻豆视频 | 超碰人人舔 | 狠狠的操狠狠的干 | 日韩一级成人av | 在线观看精品视频 | 日韩免费小视频 | 成人午夜av电影 | 高清av中文在线字幕观看1 | 国产成人久久av | 日本婷婷色| 欧美午夜剧场 | 久av电影 | 亚洲激情校园春色 | 亚洲精品在线一区二区 | 人人爽夜夜爽 | 91av资源在线| 99久久er热在这里只有精品66 | 99视频一区二区 | 成人黄色小视频 | 日韩欧美国产激情在线播放 | 日韩成人av在线 | 精品亚洲午夜久久久久91 | 久久国产精品成人免费浪潮 | 亚洲欧美日韩一区二区三区在线观看 | 亚洲成aⅴ人在线观看 | 黄av在线 | 激情综合网在线观看 | 婷婷久月 | 蜜臀av麻豆 | 国产精品美女网站 | 欧美日韩高清一区二区三区 | 在线观看一级片 | 久久激情五月丁香伊人 | www.日日操.com| 国产精品 中文在线 | 国产综合在线视频 | 成人三级黄色 | 久久99精品久久久久久秒播蜜臀 | 欧美午夜久久 | 亚洲在线激情 | 精品久久久久久综合 | 国产资源网 | 中文视频一区二区 | 玖玖精品在线 | 色综合久久久久综合体桃花网 | 日韩精品一区在线播放 | 亚洲电影网站 | www.xxxx欧美 | 麻豆免费看片 | 亚州视频在线 | 婷婷色网 | 中文字幕观看视频 | 美女视频久久久 | 国产福利精品在线观看 | 中文字幕视频播放 | 亚洲专区欧美 | 在线久草视频 | 亚洲h视频在线 | 久久久国产精华液 | 国产视频亚洲精品 | 日韩精品电影在线播放 | 2019精品手机国产品在线 | 国产精品久久久久久久av大片 | 亚洲欧洲av | 免费激情网 | 一区二三国产 | 国产日韩精品一区二区三区 | 九九三级毛片 | 最新色站 | 中文字幕av在线播放 | 天天射,天天干 | 91大神免费在线观看 | 一区二区三区四区五区在线 | 国产黄色片久久久 | 亚洲永久精品在线 | 视频在线91 | 最近中文字幕高清字幕在线视频 | 日韩欧美一区二区三区在线 | 伊人超碰在线 | 99中文字幕 | 国产精品成人av在线 | 天天综合网 天天 | 国产成人久久av977小说 | 久久艹艹 | 国产高清日韩欧美 | 97人人添人澡人人爽超碰动图 | 日韩中文字幕一区 | 国内精品久久久精品电影院 | 久久在线观看 | 免费在线电影网址大全 | 五月天网页 | 亚洲中字幕 | 九九久久婷婷 | 99精品免费久久久久久久久 | 久久人人97超碰精品888 | 国产午夜小视频 | 色资源网在线观看 | 蜜臀av性久久久久av蜜臀妖精 | 四虎免费av | 欧美 日韩 国产 成人 在线 | 又黄又刺激的网站 | 丁香婷婷深情五月亚洲 | 久久久国产影视 | 久久久久免费网 | 天天躁天天狠天天透 | 久久国产精品久久w女人spa | 麻豆久久久久久久 | 久久精品欧美日韩精品 | 国产日产欧美在线观看 | 91在线一区 | 久久欧美精品 | 国产精品久久久久久久av大片 | av短片在线| 久久久久久久免费观看 | 天天操夜操视频 | 欧美一区二区三区在线看 | 国产在线播放一区二区三区 | 国产亚洲精品xxoo | 伊人射 | 国产午夜三级一二三区 | 色网站中文字幕 | 麻豆精品在线视频 | 久久国产精品久久久 | 久精品一区 | 六月色婷婷 | 国产一区在线视频观看 | 成人一级 | 一区二区三区高清在线 | 2019久久精品 | 亚洲精品久久久久中文字幕二区 | 999视频精品 | 久热香蕉视频 | 在线激情影院一区 | 精品国产一区二区三区久久久蜜月 | 成人香蕉视频 | 欧美日韩精品影院 | 永久免费毛片在线观看 | 欧洲成人免费 | 五月天婷亚洲天综合网鲁鲁鲁 | 欧美三人交 | 国产特级毛片aaaaaaa高清 | 久久国产精品99久久久久久进口 | 一 级 黄 色 片免费看的 | 一区二区三区四区五区在线 | 亚洲一区视频在线播放 | 日韩中文字幕亚洲一区二区va在线 | 91色吧 | 天天色天天射综合网 | 伊人天天操 | 成人影视免费看 | 欧美久久综合 | 成年美女黄网站色大片免费看 | 中文字幕有码在线播放 | 日韩av二区 | 91欧美视频网站 | 天天爽夜夜爽精品视频婷婷 | 91精品久久久久久久91蜜桃 | 亚洲在线视频网站 | 91精品推荐| 久久久免费在线观看 | 婷婷综合网 | 久久综合久久88 | 六月丁香色婷婷 | 91精品国产99久久久久 | 久久婷婷色 | 色成人亚洲 | 国产99亚洲 | 欧美在线视频日韩 | 国内精品一区二区 | 日韩精品在线播放 | 亚洲精品麻豆 | 视频福利在线 | 日韩成人在线一区二区 | 黄色特一级片 | 欧美日韩xxxxx | 97在线观看免费高清完整版在线观看 | 精品a在线 | 99久久久国产精品免费99 | 欧美日韩首页 | 亚洲一级电影 | 免费看一级黄色大全 | 国产精品一区二区久久久久 | 91看片淫黄大片在线播放 | 日本动漫做毛片一区二区 | 久久国产三级 | 日韩电影一区二区在线 | 午夜色婷婷 | 人人干人人草 | 99精品亚洲 | 精品毛片久久久久久 | www.黄色网.com | 天天干天天干天天干天天干天天干天天干 | 黄色软件网站在线观看 | 亚洲精品午夜久久久久久久久久久 | 亚洲精品网址在线观看 | 免费a v在线 | 中文字幕观看在线 | 91经典在线| 色综合久久久网 | 成人av免费播放 | 精品久久久久久久久久久久久久久久 | 成人黄色大片在线观看 | 天天操天天射天天爽 | 九色视频网址 | 欧美日韩视频网站 | 欧美一级乱黄 | 国产高清在线a视频大全 | 亚洲精品视频第一页 | 一区二区三区四区五区在线 | 天堂av在线网站 | 99国产高清| 中文字幕第一 | 国产99久久精品一区二区永久免费 | 日韩在线资源 | 人人超在线公开视频 | 69xxxx欧美 | 日韩黄色一级电影 | 99国产情侣在线播放 | 97香蕉久久国产在线观看 | 欧美福利久久 | 亚洲精品国产第一综合99久久 | 色在线国产 | 久久蜜臀av | 伊人久久一区 | 亚洲另类视频在线 | 日本久久久久久科技有限公司 | 国产成人精品一区一区一区 | 中文字幕免费高清av | 国产精品一区二区三区电影 | 超碰免费观看 | 国产精品永久免费 | 综合色久| 久久久成人精品 | 丰满少妇在线观看资源站 | 国产手机在线视频 | 最新日韩精品 | 国产91精品欧美 | 日韩毛片精品 | 91免费观看视频网站 | 久久久久 | 午夜国产一区二区三区四区 | 免费在线黄 | 国产一级片久久 | 怡春院av| 天天激情天天干 | 亚洲成a人片77777潘金莲 | 国产高清专区 | 国产精品视频地址 | 91亚洲狠狠婷婷综合久久久 | 国产精品片 | 国产亚洲精品女人久久久久久 | 最新av中文字幕 | 国产永久网站 | 在线av资源 | 色大片免费看 | 日韩免费在线观看网站 | 一级理论片在线观看 | 7799av | 中文字幕在线高清 | 亚洲精品一区二区三区在线观看 | 天天操天天操天天爽 | 国产精品毛片一区二区在线看 | 97成人免费视频 | 久久亚洲国产精品 | 天天干.com| 国产99久久精品一区二区永久免费 | 免费在线观看国产黄 | 天天激情综合网 | 国产乱老熟视频网88av | 波多野结衣小视频 | 亚洲最新毛片 | 天天操福利视频 | 波多野结依在线观看 | 婷婷丁香六月 | 在线成人一区 | 91色九色 | 狠狠色丁香 | 中文字幕精品三区 | 久草在线欧美 | 亚洲九九九在线观看 | 在线欧美国产 | 亚洲国产中文字幕在线视频综合 | 久久久久久看片 | 在线之家免费在线观看电影 | 久久久久久久久久久久久久免费看 | 中文字幕久久久精品 | 日日天天av| 精品99在线观看 | 中文字幕高清有码 | 狠狠色丁香婷婷 | 国产成人精品亚洲日本在线观看 | 国产精品久久久久久久久久久久午 | 婷婷激情欧美 | 国产精品自在欧美一区 | 国内精品久久久久久久影视麻豆 | 91成人免费在线视频 | 五月婷婷在线视频 | 在线观看完整版 | 超碰在线观看97 | 国产一区网| 欧美成人视 | 国产 日韩 在线 亚洲 字幕 中文 | 成年人在线免费看视频 | 国产成人av免费在线观看 | av千婊在线免费观看 | 天天操夜夜操国产精品 | 91片黄在线观看动漫 | 亚洲狠狠婷婷综合久久久 | 91精品久久香蕉国产线看观看 | 免费视频在线观看网站 | 人人干天天干 | 国产日韩欧美在线免费观看 | 一区二区三区免费网站 | 国产1区2 | 欧美在线资源 | 国产亚洲aⅴaaaaaa毛片 | 国产精品资源在线观看 | 国产aaa免费视频 | 看片黄网站 | 免费美女久久99 | 丁香六月久久综合狠狠色 | 黄色字幕网 | 国产高清日韩 | 国内精品久久久久久久久久久久 | 99婷婷狠狠成为人免费视频 | 久久成年人| 国产一区二区久久久久 | 久久婷婷久久 | 美女av在线免费 | 国产中文字幕在线播放 | 国产精品久久99综合免费观看尤物 | 国产亚洲精品久 | 久久国产精品久久w女人spa | 亚洲精品1234区 | 国产一区二区免费在线观看 | 国产一级a毛片视频爆浆 | 天堂av网址 | 日韩亚洲在线视频 | 人人插人人做 | 精品国产精品国产偷麻豆 | 福利区在线观看 | 美女精品国产 | 日韩国产精品毛片 | www黄色软件 | 中文字幕第一页在线 | 久久综合色天天久久综合图片 | 久久亚洲国产精品 | 中文字幕在线看视频 | 欧美91精品国产自产 | 国产精品第三页 | 久草电影免费在线观看 | 天天操天天弄 | 久久久亚洲麻豆日韩精品一区三区 | 欧美在线1| 久久免费黄色 | 国产激情电影综合在线看 | 99视频久久 | 久久国内精品99久久6app | 丰满少妇在线观看资源站 | 国产不卡在线视频 | 日本黄色免费电影网站 | 91人人揉日日捏人人看 | 欧美日韩高清一区二区 国产亚洲免费看 | 全黄色一级片 | 日本三级久久 | 亚洲国产97在线精品一区 | 韩国视频一区二区三区 | 欧美激情第一区 | 日本精品久久久久中文字幕5 | 丁香久久激情 | 国产午夜精品视频 | 4438全国亚洲精品观看视频 | 久久xx视频 | 特黄特色特刺激视频免费播放 | 最近2019年日本中文免费字幕 | 黄色资源在线 | 精品美女久久久久久免费 | 超碰午夜| 美女黄频网站 | 国产精品xxxx18a99 | 国产亚洲精品久久久久久久久久久久 | 日韩一区二区免费播放 | 成人av.com| 国产精品久久久久久久毛片 | 成人精品99 | 制服丝袜成人在线 | 91色在线观看 | 91资源在线播放 | 91看片在线 | 99久热在线精品视频观看 | 免费看色网站 | 中文字幕在线观看av | av不卡中文字幕 | 久久久久高清毛片一级 | 美女久久久久久久久久久 | 国产亚洲精品综合一区91 | 一区二区视频在线免费观看 | 亚洲精品久久久久久久不卡四虎 | 亚洲特级毛片 | 亚洲精品www | 99精品国产高清在线观看 | 欧美精品久久久久久久亚洲调教 | 久久艹欧美 | 973理论片235影院9 | 中文在线免费观看 | 欧洲亚洲女同hd | 中文字幕一二三区 | 中文字幕一区二区三区视频 | 久久久久福利视频 | 91视视频在线直接观看在线看网页在线看 | 亚洲网站在线 | 久久久精品成人 | 国产另类av | 国产真实精品久久二三区 | 日韩欧美亚州 | 中文在线字幕观看电影 | 最近能播放的中文字幕 | 婷婷色狠狠 | www最近高清中文国语在线观看 | 久久综合一本 | 色综合久久中文字幕综合网 | 91麻豆精品国产91久久久无需广告 | 日本精品在线看 | 国产中文a | 精品国产不卡 | 国产视频一区二区在线观看 | 天天躁日日躁狠狠躁av中文 | 国内精品美女在线观看 | 亚洲在线免费视频 | 中文字幕日韩电影 | 91九色国产视频 | 特级毛片在线观看 | 国产精品一区二区av影院萌芽 | 免费网址你懂的 | 尤物一区二区三区 | 草久久久 | 国产精品 日韩精品 | 亚洲不卡在线 | 伊人婷婷 | 国产99免费 | 国产成人一区二区三区免费看 | 欧美精品久久久久性色 | 国产精品男女啪啪 | 久久免费视频在线观看6 | 国产五码一区 | 99精品小视频 | 91在线视频网址 | 亚洲欧美激情插 | 欧美日韩中文国产 | 免费在线观看av的网站 | 国产九色视频在线观看 | 99爱视频 | 免费久久99精品国产婷婷六月 | 97精品国产一二三产区 | 9797在线看片亚洲精品 | 久久a久久 | 欧美视频在线二区 | 国产婷婷vvvv激情久 | 成人资源在线播放 | 亚洲永久精品在线 | 波多野结衣动态图 | 中文字幕亚洲精品在线观看 | 91精品在线免费观看视频 | 亚洲乱码国产乱码精品天美传媒 | 国产精品美女久久久久久久网站 | 天堂av在线7| 国产一区免费观看 | 99视频在线免费播放 | 久久国产精品99国产 | av大片免费在线观看 | 九九视频精品免费 | 欧美一级看片 | 国产精品久久在线 | 久久首页| 69国产盗摄一区二区三区五区 | 天天插天天色 | 中文字幕日韩电影 | av在线影视 | 99久久99久久 | 欧美日韩视频网站 | 欧美日韩高清一区 | 日韩精品久久一区二区 | 色综合天天综合在线视频 | 美女在线免费视频 | 国产精品美乳一区二区免费 | 精品美女在线视频 | 四虎影视成人永久免费观看亚洲欧美 | 日本中文字幕在线观看 | 在线电影a| 六月丁香久久 | 九九欧美视频 | av丝袜美腿 | 亚洲精品在线电影 | 999国内精品永久免费视频 | 日韩欧美69 | 日韩在线视频一区二区三区 | 人人射人人插 | 国产精品久久久久久久久久免费看 | 最近中文字幕免费av | 热久久视久久精品18亚洲精品 | 在线观看中文字幕2021 | 国产精品欧美日韩在线观看 | 啪啪激情网 | 四虎国产 | 久久噜噜少妇网站 | 亚洲黄a | 超碰97人 | www,黄视频| 探花视频在线版播放免费观看 | 亚洲欧美日韩不卡 | 欧美一级黄色视屏 | 国产91成人在在线播放 | 国产美女在线免费观看 | 久久精品视频网址 | 欧美日韩三级 | 欧美黄色高清 | 中文字幕一区二区在线观看 | 久久在现| 亚洲午夜不卡 | 高清中文字幕av | 九色91在线视频 | 国产91精品在线观看 | 91精品一区二区三区蜜臀 | av女优中文字幕在线观看 | 久久精品亚洲一区二区三区观看模式 | 91成人免费看片 | 天天草天天插 | 456免费视频| 国产在线观看一 | 在线播放 日韩专区 | www.夜色.com| 久草在线免费看视频 | 一区二区三区国产欧美 | www.夜夜爱| 国内外激情视频 | 日韩一级片观看 | 中文av在线免费观看 | 成人av在线一区二区 | 精品国产诱惑 | 日本中文乱码卡一卡二新区 | 婷婷精品视频 | 国产精品国内免费一区二区三区 | 亚洲播放一区 | 国产高清一区二区 | 亚洲最大免费成人网 | 在线国产99 | 久草爱视频 | 婷婷视频 | avhd高清在线谜片 | 五月婷婷综合网 | 国产精品12| 香蕉视频久久久 | 国产精品久久久久久久久岛 | 黄色的网站免费看 | 狠狠色狠狠色综合日日小说 | 激情综合中文娱乐网 | 国产不卡精品 | 免费av观看 | 99久热在线精品视频观看 | 国产成人在线播放 | 最近更新的中文字幕 | 超碰97人人爱 | 久久久免费在线观看 | 亚洲日本va午夜在线影院 | 婷婷色在线资源 | 综合色站导航 | 中中文字幕av | 久久久在线观看 | 国产精品久久久久久久av电影 | 夜夜爽www| 欧美精品久久久久久久 | 国产精品入口麻豆www | 亚洲国产精品视频在线观看 | 久久久久久久久久久影视 | 免费成人在线观看 | 天天插日日操 | 开心激情五月婷婷 |