手把手帶你入門Python

0. 序言

  • python 是一門腳本語言:封裝性強,語法簡潔,開發效率高,只用函數open就可以打開一個txt文件,只需要遍歷就能讀取這個txt文件。因為以上原因,python也廣泛用于爬蟲、數據處理和大數據以及人工智能,現在是大數據時代,所以python很火。如果是計算機研究生畢業,可以考慮人工智能,因為人工智能的崗位在學歷方面卡的比較嚴,需要對算法數據結構等理論知識非常熟悉。
  • python是一門解釋性語言,代碼執行效率沒有java和c++高,但是取決于效率的主要是io和數據庫的crud,所以python在以上場景下表現依然很優秀。因為就算你是法拉利,在北京二環上,你的速度等同于天津大發面包車。
  • 學習python,以個人經歷來看,不用購買python基礎方面的書籍,慕課網的python入門和進階兩門課可以讓你熟練掌握大部分python語法。不過在學習python之前,你最好問問自己Android進階之光這本書涉及的板塊以及binder原理是否都弄清楚了,如果說ok,那建議周末打游戲的時間學python,如果說no,那建議好好研究Android,畢竟去面試的崗位叫Android開發工程師,問的基本是java基礎和android理論。當然工作需要例外。
  • 因為工作需要,學習了下python基礎知識,于是有了這篇博客!這篇博客主要總結了以下幾個方面的知識,這些知識不得不牢牢掌握:
    ① 安裝Python環境
    ② 變量和數據類型:Python內置的基本類型
    ③ List和Tuple:順序的集合類型
    ④ 條件判斷和循環:控制程序流程
    ⑤ Dict和Set:根據key訪問的集合類型
    ⑥ 函數:定義和調用函數
    ⑦ 切片:如何對list進行切片
    ⑧ 迭代:如何用for循環迭代集合類型
    ⑨ 列表生成式:如何快速生成列表

1. Python之禪

  • 人生苦短,我用Python.

2. 開發者

  • 由荷蘭人Guido van Rossum于1989年為了打發圣誕節的無聊而開發。

3. 特點

  • 優雅
  • 明確
  • 簡潔

4. 適用領域

  • Web網站和各種網絡服務
  • 系統工具和腳本
  • 作為“膠水”語言把其他語言開發的模塊包裝起來方便使用

5. 不適用的領域

  • 貼近硬件的開發:比如 驅動程序 ----首選C
  • 移動領域的開發:比如 Android Ios -----Swift、Kotlin
  • 游戲開發:C/C++

6. Python的應用

  • Youtube
  • 豆瓣
  • 閃電郵箱
  • openstack 開源云計算平臺

7. 與其他語言的對比的缺點

  • C: 編譯為機器碼 運行速度非常快 代碼量非常多
  • Java:編譯為字節碼 運行速度快 代碼量多
  • Python缺點
    ①:解釋執行 運行速度慢 代碼量少(開發速度快);但是:我們并不需要運行速度那么快,速度瓶頸還是取決于網絡調用和數據庫操作,就好比F1在北京的三環高速公路上,堵車你也開不了那么快。
    ②:Python源碼不能夠加密:所以通過Python提供服務賺錢。

8. 安裝

  • Python跨平臺:Window開發的,可以運行在Mac、Linux等系統上。
  • 很多庫暫時不兼容3.3,所以暫時安裝Python 2.7
  • 官網:https://www.python.org/
  • 步驟:Downloads_Window_2.7.14
  • 下載完成_一直Next即可。

9. 安裝環境

  • E:\Python 添加到Path中即可
  • 命令行輸入 python 顯示版本號 證明安裝正確
  • 建議使用cmder這款命令行工具

10. 第一個Python程序-Hello World (初戀的感覺)

  • 命令行:打開命令行工具cmder,輸入第一個Python程序
>>> print 'Hello,World!'
Hello,World!
  • NotePad:

① 設置:首選項-新建-windows-utf-8 ② 語言:python

print 'Hello,World!'  記得一定要定格左邊寫 保存為擴展名為py的文件

② 打印: 進入到文件所在盤符,打開命令行,然后輸入python helloworld.py:

D:\>python helloworld.py
Hello,World!

11. 數據類型

  • 整數:
  1. 整數的書寫和數學一樣,而且有負整數,如 0,-80
  2. 機器采用二進制,我們使用十六進制(0x開頭,由0-9,a-f組成)表示整數更好,如 0x10,0xaf10
  • 浮點數:
  1. 浮點數就是小號:比如1.23,2.31,而對于很大或者很小的浮點數,就必須用科學計數法表示:把10用e替代,比如1.23x10^9就是1.23e9,再比如0.000012可以寫成1.2e-5。
  2. 注意:整數和浮點數在計算機中的存儲方式是不同的,整數的運算永遠是精確的(除法也是精確的),而浮點數在運算中會有誤差。
  • 字符串:字符串可以用單引號或者多引號包裹起來表示:"abc",'abc'

  • 布爾值:

  1. 布爾值指的是True或者False,非0就是Ture,0就是False
  2. 布爾值的運算可以通過運算符來進行:and(有false則false),or(有true則true),not(把true變為false或者false變為true)
  • 空值:空值用none表示,none不表示為0,0是有意義的,None是一個特殊的空值。

  • 練習:
    試一試,在右邊編輯器中,完成以下任務:

  1. 計算十進制整數 45678 和十六進制整數 0x12fd2 之和。
  2. 請用字符串表示出Learn Python in imooc。
  3. 請計算以下表達式的布爾值(注意==表示判斷是否相等):
    100 < 99
    0xff == 255
    注意:使用print命令
print 45678+0x12fd2
print "Learn Python in imooc"
print 100<99
123456
Learn Python in imooc
False

12. print語句

  1. 多個字符串可以用“,”逗號來進行連接,然后直接一起輸出:
    (print 會依次打印每個字符串,遇到逗號就插入一個空格)
print 'hello','world','you','and','me'
hello world you and me
  1. 可以打印整數
print 300+500
800
  1. 注意(字符串、逗號、數學計算):
print '100+200=',100+200
100+200= 300

13. 注釋

print 'hello,world' # 這是我的第一個Python程序
File "index.py", line 1
SyntaxError: Non-ASCII character '\xe8' in file index.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
  • 這是缺乏編碼方式導致的,所以在文件頭部添加:
# coding=utf-8
  • 完整代碼:
# coding=utf-8
print 'hello,world' # 這是我的第一個Python程序
  • 注釋代碼:
# print 'hello,world'

14. 變量

  • 變量名:大小寫英文或者英文加數字或者英文加數字加下劃線的組合:
x1 = 1
d = 3
x100 = x1+d
_d100 = x100
s = _d100
print s
a = 1 # a是一個整數
t_007 = 'T007' t_007是一個字符串
  • 等號=是賦值語句,可以把任意數據類型賦值給變量,同一個變量可以反復賦值,而且可以是不同類型的變量:
a = 123    # a是整數
print a
a = 'imooc'   # a變為字符串
print a

這種變量本身類型不固定的語言稱之為動態語言,與之對應的是靜態語言。
  • 當我們寫:a = 'ABC'時,Python解釋器干了兩件事情:
  1. 在內存中創建了一個'ABC'的字符串;
  2. 在內存中創建了一個名為a的變量,并把它指向'ABC'。

15. 小測驗

  • 等差數列可以定義為每一項與它的前一項的差等于一個常數,可以用變量 x1 表示等差數列的第一項,用 d 表示公差,請計算數列
    1 4 7 10 13 16 19 ...
    前 100 項的和。
a = 1
x1 = 3
a_100 = 1+x1*99
print (a_100+a)*50
14950

16. 定義字符串

  • 如果字符串本身包含'怎么辦?比如我們要表示字符串 I'm OK ,這時,可以用" "括起來表示:
"I'm OK"
  • 如果字符串包含",我們就可以用' '括起來表示:
'Learn "Python" in imooc'
  • 如果字符串既包含'又包含",這個時候,就需要對字符串的某些特殊字符進行“轉義”,Python字符串用\進行轉義,比如要表示字符串 Bob said "I'm OK".
    由于 ' 和 " 會引起歧義,因此,我們在它前面插入一個\表示這是一個普通字符,不代表字符串的起始
'Bob said \"I\'m OK\".'
  • 常用的轉義字符:
\n 表示換行
\t 表示一個制表符
\\ 表示 \ 字符本身

17. raw字符串與多行字符串

  • raw:
r'\(~_~)/ \(~_~)/'
  • 多行:
'''Line 1
Line 2
Line 3'''
  • 注意:r'...'表示法不能表示多行字符串,也不能表示包含'和 "的字符串,但是r''' '''可以:
print r'''"To be, or not to be": that is the question.
Whether it's nobler in the mind to suffer.'''

18. Unicode字符串

  • 計算機只能處理數字,如果要處理文本,就必須先把文本轉換為數字才能處理。最早的計算機在設計時采用8個比特(bit)作為一個字節(byte),所以,一個字節能表示的最多個數是(二進制11111111=十進制255),0 - 127被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱為ASCII編碼,比如大寫字母 A 的編碼是65,小寫字母 z 的編碼是122。

  • 如果要表示中文,顯然一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII編碼沖突,所以,中國制定了GB2312編碼,用來把中文編進去。

  • 類似的,日文和韓文等其他語言也有這個問題。為了統一所有文字的編碼,Unicode應運而生。Unicode把所有語言都統一到一套編碼里,這樣就不會再有亂碼問題了。

  • Unicode通常用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只需要把高字節全部填為0就可以

  • 為Python的誕生比Unicode標準發布的時間還要早,所以最早的Python只支持ASCII編碼,普通的字符串'ABC'在Python內部都是ASCII編碼的。

  • Python在后來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示。

  • Python在后來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:

print u'中文'
中文
  • Unicode字符串除了多了一個 u 之外,與普通字符串沒啥區別,轉義字符和多行表示法仍然有效:
u'中文\n日文\n韓文'
u'''第一行
第二行'''
ur'''Python的Unicode字符串支持"中文",
"日文",
"韓文"等多種語言'''
  • 如果中文字符串在Python環境下遇到 UnicodeDecodeError,這是因為.py文件保存的格式有問題。可以在第一行添加注釋,目的是告訴Python解釋器,用UTF-8編碼讀取源代碼
# -*- coding: utf-8 -*-

19. 整數和浮點數

  • 整數和浮點數直接進行運算
1 + 2 + 3   # ==> 6
4 * 5 - 6   # ==> 14
7.5 / 8 + 2.1   # ==> 3.0375
  • 使用括號可以提升優先級
(1 + 2) * 3    # ==> 9
(2.2 + 3.3) / (1.5 * (9 - 0.3))    # ==> 0.42145593869731807
  • 和數學運算不同的地方是,Python的整數運算結果仍然是整數,浮點數運算結果仍然是浮點數:
1 + 2    # ==> 整數 3
1.0 + 2.0    # ==> 浮點數 3.0
  • 整數和浮點數混合運算的結果就變成浮點數了
1 + 2.0    # ==> 浮點數 3.0
  • Python的整數除法,即使除不盡,結果仍然是整數,余數直接被扔掉。不過,Python提供了一個求余的運算 % 可以計算余數:
11 % 4    # ==> 3
  • 如果我們要計算 11 / 4 的精確結果,按照“整數和浮點數混合運算的結果是浮點數”的法則,把兩個數中的一個變成浮點數再運算就沒問題了:
11.0 / 4    # ==> 2.75

20.布爾類型

  • 與運算:有false則false。
True and True   # ==> True
True and False   # ==> False
False and True   # ==> False
False and False   # ==> False
  • 或運算:有true則true。
True or True   # ==> True
True or False   # ==> True
False or True   # ==> True
False or False   # ==> False
  • 非運算:把True變為False,或者把False變為True:
not True   # ==> False
not False   # ==> True
  • 布爾類型還可以與其他數據類型做 and、or和not運算
a = True
print a and 'a=T' or 'a=F'
  • Python把0、空字符串''和None看成 False,其他數值和非空字符串都看成 True。

  • and 和 or 運算的一條重要法則:短路計算。計算 a and b 時,如果 a 是 False,則根據與運算法則,整個結果必定為 False,因此返回 a;如果 a 是 True,則整個計算結果必定取決與 b,因此返回 b。

  • 計算 a or b 時,如果 a 是 True,則根據或運算法則,整個計算結果必定為 True,因此返回 a;如果 a 是 False,則整個計算結果必定取決于 b,因此返回 b。

21. 創建list

  • list是一種有序的集合,可以隨時添加和刪除其中的元素:
>>> ['Michael', 'Bob', 'Tracy']
['Michael', 'Bob', 'Tracy']
  • 直接用 [ ] 把list的所有元素都括起來,就是一個list對象。通常,我們會把list賦值給一個變量,這樣,就可以通過變量來引用list:
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates # 打印classmates變量的內容
['Michael', 'Bob', 'Tracy']
  • Python是動態語言,所以list中包含的元素并不要求都必須是同一種數據類型,我們完全可以在list中包含各種數據:
>>> L = ['Michael', 100, True]
  • 一個元素也沒有的list,就是空list:
>>> empty_list = []

22. 按照索引訪問list

  • 要打印第一名同學的名字,用 L[0]:
>>> L = ['Adam', 'Lisa', 'Bart']
>>> print L[0]
Adam

23. 倒序訪問list:

>>> L = ['Adam', 'Lisa', 'Bart']
>>> print L[-1]
Bart

24. list添加新元素:

  • append() 方法(總是把新的元素添加到 list 的尾部):
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.append('Paul')
>>> print L
['Adam', 'Lisa', 'Bart', 'Paul']
  • insert()方法,它接受兩個參數,第一個參數是索引號,第二個參數是待添加的新元素:
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L.insert(0, 'Paul')
>>> print L
['Paul', 'Adam', 'Lisa', 'Bart']

25. list刪除元素

  • pop():
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L.pop()
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
pop()方法總是刪掉list的最后一個元素,并且它還返回這個元素,所以我們執行 L.pop() 后,會打印出 'Paul'
  • pop(2):
>>> L.pop(2)
'Paul'
>>> print L
['Adam', 'Lisa', 'Bart']
  • 小練習:
L = ['Adam', 'Lisa', 'Paul', 'Bart']
Paul的索引是2,Bart的索引是3,如果我們要把Paul和Bart都刪掉
L = ['Adam', 'Lisa', 'Paul', 'Bart']
L.pop(2)
L.pop(2)
print L

26. 替換元素

  • 對list中的某一個索引賦值,就可以直接用新的元素替換掉原來的元素,list包含的元素個數保持不變
>>> L = ['Adam', 'Lisa', 'Bart']
>>> L[2] = 'Paul'
>>> print L
L = ['Adam', 'Lisa', 'Paul']

27. 創建tuple

  • tuple是另一種有序的列表,中文翻譯為“ 元組 ”。tuple 和 list 非常類似,但是,tuple一旦創建完畢,就不能修改了。
>>> t = ('Adam', 'Lisa', 'Bart')

創建tuple和創建list唯一不同之處是用( )替代了[ ]

獲取 tuple 元素的方式和 list 是一模一樣的,我們可以正常使用 t[0],t[-1]等索引方式訪問元素

28. 創建單元素tuple

  • 包含 0 個元素的 tuple,也就是空tuple,直接用 ()表示
>>> t = ()
>>> print t
()
  • 創建包含1個元素的 tuple
>>> t = (1,)
>>> print t
(1,)

因為用()定義單元素的tuple有歧義,所以 Python 規定,單元素 tuple 要多加一個逗號“,”

29. “可變”的tuple

>>> t = ('a', 'b', ['A', 'B'])
>>> L = t[2]
>>> L[0] = 'X'
>>> L[1] = 'Y'
>>> print t
('a', 'b', ['X', 'Y'])
  • 注意:tuple的元素確實變了,但其實變的不是 tuple 的元素,而是list的元素。

  • tuple一開始指向的list并沒有改成別的list,所以,tuple所謂的“不變”是說,tuple的每個元素,指向永遠不變。即指向'a',就不能改成指向'b',指向一個list,就不能改成指向其他對象,但指向的這個list本身是可變的!

  • 理解了“指向不變”后,要創建一個內容也不變的tuple怎么做?那就必須保證tuple的每一個元素本身也不能變。

  • 小練習:定義了tuple:
    t = ('a', 'b', ['A', 'B'])
    由于 t 包含一個list元素,導致tuple的內容是可變的。能否修改上述代碼,讓tuple內容不可變?

t = ('a', 'b', ('A', 'B'))
print t

29. if語句

age = 20
if age >= 18:
    print 'your age is', age
    print 'adult'
print 'END'
  • 注意: Python代碼的縮進規則。具有相同縮進的代碼被視為代碼塊,上面的3,4行 print 語句就構成一個代碼塊(但不包括第5行的print)。如果 if 語句判斷為 True,就會執行這個代碼塊。

  • 縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab,更不要混合Tab和空格,否則很容易造成因為縮進引起的語法錯誤。

  • 注意: if 語句后接表達式,然后用:表示代碼塊開始。

  • 如果你在Python交互環境下敲代碼,還要特別留意縮進,并且退出縮進需要多敲一行回車:

>>> age = 20
>>> if age >= 18:
...     print 'your age is', age
...     print 'adult'
...
your age is 20
adult

30. if-else

if age >= 18:
    print 'adult'
else:
    print 'teenager'
  • 注意: else 后面有個“:”

31. if-elif-else

條件1:18歲或以上:adult
條件2:6歲或以上:teenager
條件3:6歲以下:kid
if age >= 18:
    print 'adult'
elif age >= 6:
    print 'teenager'
elif age >= 3:
    print 'kid'
else:
    print 'baby'
  • 特別注意: 這一系列條件判斷會從上到下依次判斷,如果某個判斷為 True,執行完對應的代碼塊,后面的條件判斷就直接忽略,不再執行了。

32. for

L = ['Adam', 'Lisa', 'Bart']
for name in L:
    print name
  • 注意: name 這個變量是在 for 循環中定義的,意思是,依次取出list中的每一個元素,并把元素賦值給 name,然后執行for循環體(就是縮進的代碼塊)。

  • 小練習:班里考試后,老師要統計平均成績,已知4位同學的成績用list表示如下:
    L = [75, 92, 59, 68]
    請利用for循環計算出平均成績。

L = [75, 92, 59, 68]
sum = 0.0
for score in L:
    sum = sum + score
print sum / 4

33. while循環

  • while 循環不會迭代 list 或 tuple 的元素,而是根據表達式判斷循環是否結束:比如要從 0 開始打印不大于 N 的整數:
N = 10
x = 0
while x < N:
    print x
    x = x + 1
  • 小練習:利用while循環計算100以內奇數的和
sum = 0
x = 1
while x < 100:
    sum = sum + x
    x = x + 2
print sum

34. break退出循環

  • 比如計算1至100的整數和,我們用while來實現
sum = 0
x = 1
while True:
    sum = sum + x
    x = x + 1
    if x > 100:
        break
print sum
  • 小練習:利用 while True 無限循環配合 break 語句,計算 1 + 2 + 4 + 8 + 16 + ... 的前20項的和:
sum = 0
x = 1
n = 1
while True:
    sum = sum + x
    x = 2*x
    n = n+1
    if n > 20:
        break
print sum

35. continue繼續循環

  • continue跳過后續循環代碼,繼續下一次循環:

    現在老師只想統計及格分數的平均分,就要把 x < 60 的分數剔除掉,這時,利用 continue,可以做到當 x < 60的時候,不繼續執行循環體的后續代碼,直接進入下一次循環:

L = [75, 98, 59, 81, 66, 43, 69, 85]
sum = 0.0
n = 0
for x in L:
    sum = sum + x
    n = n + 1
print sum / n
for x in L:
    if x < 60:
        continue
    sum = sum + x
    n = n + 1
  • 小練習:

    對已有的計算 0 - 100 的while循環進行改造,通過增加 continue 語句,使得只計算奇數的和

sum = 0
x = 1
while True:
    sum = sum + x
    x = x + 1
    if x > 100:
        break
print sum
sum = 0
x = 0
while True:
    x = x + 1
    if x > 100:
        break
    if x % 2 == 0:
        continue
    sum = sum + x
print sum

36. 多重循環

  • 在循環內部,還可以嵌套循環
for x in ['A', 'B', 'C']:
    for y in ['1', '2', '3']:
        print x + y
A1
A2
A3
B1
B2
B3
C1
C2
C3
  • 小練習:對100以內的兩位數,請使用一個兩重循環打印出所有十位數數字比個位數數字小的數,例如,23(2 < 3)
for x in [1,2,3,4,5,6,7,8,9 ]:
    for y in [ 0,1,2,3,4,5,6,7,8,9 ]:
        if x < y :
            print x*10+y

37. dict

  • 給定一個名字,就可以直接查到分數,這就是dict的作用,名字稱為key,對應的成績稱為value,dict就是通過 key 來查找 value
  • 花括號 {} 表示這是一個dict,然后按照 key: value, 寫出來即可。最后一個 key: value 的逗號可以省略。
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
  • len() 函數可以計算任意集合的大小:
>>> len(d)
3

38. 訪問dict

  • 可以簡單地使用 d[key] 的形式來查找對應的 value,這和 list 很像,不同之處是,list 必須使用索引返回對應的元素,而dict使用key
>>> print d['Adam']
95
>>> print d['Paul']
Traceback (most recent call last):
  File "index.py", line 11, in <module>
    print d['Paul']
KeyError: 'Paul'
  • 通過 key 訪問 dict 的value,只要 key 存在,dict就返回對應的value。如果key不存在,會直接報錯:KeyError,要避免 KeyError 發生,有兩個辦法:
  1. 先判斷一下 key 是否存在,用 in 操作符:
if 'Paul' in d:
    print d['Paul']
  1. 使用dict本身提供的一個 get 方法,在Key不存在的時候,返回None:
>>> print d.get('Bart')
59
>>> print d.get('Paul')
None
  • 小練習:根據如下dict,請打印出:
Adam: 95
Lisa: 85
Bart: 59
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
print 'Adam:',d.get('Adam')
print 'Lisa:',d.get('Lisa')
print 'Bart:',d.get('Bart')

39. dict的特點

  • dict的第一個特點是查找速度快,無論dict有10個元素還是10萬個元素,查找速度都一樣。而list的查找速度隨著元素增加而逐漸下降。

    不過dict的查找速度快不是沒有代價的,dict的缺點是占用內存大,還會浪費很多內容,list正好相反,占用內存小,但是查找速度慢。

  • dict的第二個特點就是存儲的key-value序對是沒有順序的!這和list不一樣:

d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
>>> print d
{'Lisa': 85, 'Adam': 95, 'Bart': 59}
  • dict的第三個特點是作為 key 的元素必須不可變,Python的基本類型如字符串、整數、浮點數都是不可變的,都可以作為 key。但是list是可變的,就不能作為 key;最常用的key還是字符串,因為用起來最方便
{
    '123': [1, 2, 3],  # key 是 str,value是list
    123: '123',  # key 是 int,value 是 str
    ('a', 'b'): True  # key 是 tuple,并且tuple的每個元素都是不可變對象,value是 boolean
}

40. 更新dict

  • 隨時往dict中添加新的 key-value。比如已有dict:要把新同學'Paul'的成績 72 加進去,用賦值語句:
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
>>> d['Paul'] = 72
>>> print d
{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 59}
  • 如果 key 已經存在,則賦值會用新的 value 替換掉原來的 value:
>>> d['Bart'] = 60
>>> print d
{'Lisa': 85, 'Paul': 72, 'Adam': 95, 'Bart': 60}

41. 遍歷dict

  • 直接使用for循環可以遍歷 dict 的 key,由于通過 key 可以獲取對應的 value,因此,在循環體內,可以獲取到value的值:
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> for key in d:
...     print key
... 
Lisa
Adam
Bart
  • 小練習:請用 for 循環遍歷如下的dict,打印出 name: score 來
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
d = {
    'Adam': 95,
    'Lisa': 85,
    'Bart': 59
}
for key in d:
    print key,':',d.get(key)

42. set

  • dict的作用是建立一組 key 和一組 value 的映射關系,dict的key是不能重復的
  • 有的時候,我們只想要 dict 的 key,不關心 key 對應的 value,目的就是保證這個集合的元素不會重復,這時,set就派上用場了:
  • set 持有一系列元素,這一點和 list 很像,但是set的元素沒有重復,而且是無序的,這點和 dict 的 key很像
  • 創建 set 的方式是調用 set() 并傳入一個 list,list的元素將作為set的元素:
>>> s = set(['A', 'B', 'C'])
>>> print s
set(['A', 'C', 'B'])

上述打印的形式類似 list, 但它不是 list,仔細看還可以發現,打印的順序和原始 list 的順序有可能是不同的,因為set內部存儲的元素是無序的
  • set不能包含重復的元素,所以,當我們傳入包含重復元素的 list,set會自動去掉重復的元素,原來的list有4個元素,但set只有3個元素
>>> s = set(['A', 'B', 'C', 'C'])
>>> print s
set(['A', 'C', 'B'])
>>> len(s)
3

43. 訪問set

  • 由于set存儲的是無序集合,所以我們沒法通過索引來訪問。
  • 用 in 操作符判斷:看來大小寫很重要,'Bart' 和 'bart'被認為是兩個不同的元素:
>>> 'Bart' in s
True
>>> 'bart' in s
False

44. set的特點

  1. set的內部結構和dict很像,唯一區別是不存儲value,,因此,判斷一個元素是否在set中速度很快。
  2. set存儲的元素和dict的key類似,必須是不變對象,因此,任何可變對象是不能放入set中的.
  3. set存儲的元素也是沒有順序的.
  • 假設我們讓用戶輸入星期一至星期日的某天,如何判斷用戶的輸入是否是一個有效的星期呢?
# if 語句
x = '???' # 用戶輸入的字符串
if x!= 'MON' and x!= 'TUE' and x!= 'WED' ... and x!= 'SUN':
    print 'input error'
else:
    print 'input ok'
# set 集合
weekdays = set(['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'])

x = '???' # 用戶輸入的字符串
if x in weekdays:
    print 'input ok'
else:
    print 'input error'

45. 遍歷set

  • for 循環
>>> s = set(['Adam', 'Lisa', 'Bart'])
>>> for name in s:
...     print name
... 
Lisa
Adam
Bart
  • 小練習:請用 for 循環遍歷如下的set,打印出 name: score 來
s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
for x in s:
    print x[0]+":",x[1]
  • 注意:注意到set的元素是tuple,因此 for 循環的變量被依次賦值為tuple

46. 更新set

  • set存儲的是一組不重復的無序元素,因此,更新set主要做兩件事:一是把新的元素添加到set中,二是把已有元素從set中刪除。
  1. 增加:set的add()方法:
>>> s = set([1, 2, 3])
>>> s.add(4)
>>> print s
set([1, 2, 3, 4])
  1. 刪除:set的remove()方法:
>>> s = set([1, 2, 3, 4])
>>> s.remove(4)
>>> print s
set([1, 2, 3])
  1. Care:如果刪除的元素不存在set中,remove()會報錯:用add()可以直接添加,而remove()前需要判斷:
>>> s = set([1, 2, 3])
>>> s.remove(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 4

47. 函數

  • Python不但能非常靈活地定義函數,而且本身內置了很多有用的函數,可以直接調用,說白了函數就是方法:對公共代碼的封裝。

48. 調用函數

  • Python內置了很多有用的函數,我們可以直接調用。
  • 求絕對值的函數 abs,它接收一個參數:
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
  • 函數 cmp(x, y) 就需要兩個參數,如果 x<y,返回 -1,如果 x==y,返回 0,如果 x>y,返回 1:
>>> cmp(1, 2)
-1
>>> cmp(2, 1)
1
>>> cmp(3, 3)
0
  • 數據類型轉換函數,比如 int()函數可以把其他數據類型轉換為整數:
>>> int('123')
123
>>> int(12.34)
12
  • str()函數把其他類型轉換成 str:
>>> str(123)
'123'
>>> str(1.23)
'1.23'
  • sum()函數接受一個list作為參數,并返回list所有元素之和:請計算 1 * 1 + 2 * 2 + 3 * 3 + ... + 100 * 100:
L = []
x = 1
while x <= 100 :
    L.append(x*x)
    x = x + 1
print sum(L)

49. 編寫函數

  • 定義一個函數要使用 def 語句,依次寫出函數名、括號、括號中的參數和冒號:,然后,在縮進塊中編寫函數體,函數的返回值用 return 語句返回:
自定義一個求絕對值的 my_abs 函數:

def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x
  • 如果沒有return語句,函數執行完畢后也會返回結果,只是結果為 None 。 return None可以簡寫為return。
  • 小練習:請定義一個 square_of_sum 函數,它接受一個list,返回list中每個元素平方的和:
def square_of_sum(L):
    sum = 0
    for num in L :
        sum = num*num +sum
    return sum 

print square_of_sum([1, 2, 3, 4, 5])
print square_of_sum([-5, 0, 5, 15, 25])

50. 函數之返回多值

  • math包提供了sin()和 cos()函數,我們先用import引用它

import math
def move(x, y, step, angle):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0
  • 其實這只是一種假象,Python函數返回的仍然是單一值:返回值是一個tuple!
>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)
  • 在語法上,返回一個tuple可以省略括號,而多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,Python的函數返回多值其實就是返回一個tuple,但寫起來更方便。

  • 小練習:一元二次方程的定義是:ax2 + bx + c = 0 請編寫一個函數,返回一元二次方程的兩個解。注意:Python的math包提供了sqrt()函數用于計算平方根。請參考求根公式:x = (-b±√(b2-4ac)) / 2a

import math
def quadratic_equation(a, b, c):
    t = math.sqrt(b * b - 4 * a * c)
    return (-b + t) / (2 * a),( -b - t )/ (2 * a)
print quadratic_equation(2, 3, 0)
print quadratic_equation(1, -6, 5)

51. 遞歸函數

  • 在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數:
  • 階乘 n! = 1 * 2 * 3 * ... * n,用函數 fact(n)表示:fact(n)可以表示為 n * fact(n-1),只有n=1時需要特殊處理,于是,fact(n)用遞歸的方式寫出來就是:
fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = (n-1)! * n = fact(n-1) * n
def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
  • Care: 使用遞歸函數需要注意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由于棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。可以試試計算 fact(10000)

  • 小練習:漢諾塔 (http://baike.baidu.com/view/191666.htm) 的移動也可以看做是遞歸函數:我們對柱子編號為a, b, c,將所有圓盤從a移到c可以描述為:

    如果a只有一個圓盤,可以直接移動到c;

    如果a有N個圓盤,可以看成a有1個圓盤(底盤) + (N-1)個圓盤,首先需要把 (N-1) 個圓盤移動到 b,然后,將 a的最后一個圓盤移動到c,再將b的(N-1)個圓盤移動到c。

    請編寫一個函數,給定輸入 n, a, b, c,打印出移動的步驟:

    move(n, a, b, c)

    例如,輸入 move(2, 'A', 'B', 'C'),打印出:

    A --> B

    A --> C

    B --> C

# -*- coding: utf-8 -*
def move(n, a, b, c):
    if n > 1:
        move(n-1,a,c,b)
        print a,'-->',c
        move(n-1,b,a,c)
    else :
        print a,'-->',c

move(4, 'A', 'B', 'C')

52. 定義默認參數

  • int() 函數,其實就有兩個參數,我們既可以傳一個參數,又可以傳兩個參數:
>>> int('123')
123
>>> int('123', 8)
83
  • int()函數的第二個參數是轉換進制,如果不傳,默認是十進制 (base=10),如果傳了,就用傳入的參數
  • 函數的默認參數的作用是簡化調用,你只需要把必須的參數傳進去。
  • 但是在需要的時候,又可以傳入額外的參數來覆蓋默認參數值。
# x 的 N次方
def power(x, n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
# 把 n 的默認值設定為 2
def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
>>> power(5)
25
  • Care:由于函數的參數按從左到右的順序匹配,所以默認參數只能定義在必需參數的后面:
# OK:
def fn1(a, b=1, c=2):
    pass
# Error:
def fn2(a=1, b):
    pass
  • 小練習:請定義一個 greet() 函數,它包含一個默認參數,如果沒有傳入,打印 'Hello, world.',如果傳入,打印 'Hello, xxx.'
# 逗號如果作為連接符會生成一個空格;建議用+號連接
def greet(name = 'world'):
    print 'Hello,'+name+'.'

greet()
greet('Bart')

53. 定義可變參數

  • 可變參數的名字前面有個 * 號,我們可以傳入0個、1個或多個參數給可變參數
def fn(*args):
    print args
>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
  • Python解釋器會把傳入的一組參數組裝成一個tuple傳遞給可變參數,因此,在函數內部,直接把變量 args 看成一個 tuple 就好了
  • 定義可變參數的目的也是為了簡化調用:平均數:
>>> average()
0
>>> average(1, 2)
1.5
>>> average(1, 2, 2, 3, 4)
2.4
  • 小練習:請編寫接受可變參數的 average() 函數
# 可變參數 args 是一個tuple,當0個參數傳入時,args是一個空tuple.

def average(*args):
    sum = 0.0 
    if len(args) == 0 :
        return sum
    for x in args:
        sum = sum + x
    return sum/len(args)

print average()
print average(1, 2)
print average(1, 2, 2, 3, 4)

54. 對list進行切片

  • 切片的意思就是從中取值生成一個新的list
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[0:3]
['Adam', 'Lisa', 'Bart']

# L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素
  • 如果第一個索引是0,還可以省略:
>>> L[:3]
['Adam', 'Lisa', 'Bart']
  • 也可以從索引1開始,取出2個元素出來:
>>> L[1:3]
['Lisa', 'Bart']
  • 只用一個 : ,表示從頭到尾:L[:]實際上復制出了一個新list
>>> L[:]
['Adam', 'Lisa', 'Bart', 'Paul']
  • 切片操作還可以指定第三個參數,第三個參數表示每N個取一個,上面的 L[::2] 會每兩個元素取出一個來,也就是隔一個取一個。
>>> L[::2]
['Adam', 'Bart']
  • 把list換成tuple,切片操作完全相同,只是切片的結果也變成了tuple
  • 小練習:range()函數可以創建一個數列:請利用切片,取出:1. 前10個數;2. 3的倍數;3. 不大于50的5的倍數。
>>> range(1, 101)
[1, 2, 3, ..., 100]
L = range(1, 101)

print L[0:10]
print L[2:100:3]
print L[4:50:5]

55. 倒序切片

  • 記住倒數第一個元素的索引是-1。倒序切片包含起始索引,不包含結束索引
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']

>>> L[-2:]
['Bart', 'Paul']

>>> L[:-2]
['Adam', 'Lisa']

>>> L[-3:-1]
['Lisa', 'Bart']

>>> L[-4:-1:2]
['Adam', 'Bart']
  • 小練習:利用倒序切片對 1 - 100 的數列取出:* 最后10個數;* 最后10個5的倍數。
L = range(1, 101)
print L[-10:]
print L[-46::5]

56. 字符串切片

  • Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成,非常簡單
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[-3:]
'EFG'
>>> 'ABCDEFG'[::2]
'ACEG'
  • 小練習:字符串有個方法 upper() 可以把字符變成大寫字母:
>>> 'abc'.upper()
'ABC'

但它會把所有字母都變成大寫。請設計一個函數,它接受一個字符串,然后返回一個僅首字母變成大寫的字符串。提示:利用切片操作簡化字符串操作。

def firstCharUpper(s):
    return s[:1].upper()+s[1:]

print firstCharUpper('hello')
print firstCharUpper('sunday')
print firstCharUpper('september')

57. 迭代

  • 迭代在Python中就是 for 循環。
  • Python 的 for循環不僅可以用在list或tuple上,還可以作用在其他任何可迭代對象上。
  • 迭代操作就是對于一個集合,無論該集合是有序還是無序,我們用 for 循環總是可以依次取出集合的每一個元素
  • 集合是指包含一組元素的數據結構,我們已經介紹的包括:
  1. 有序集合:list,tuple,str和unicode;
  2. 無序集合:set
  3. 無序集合并且具有 key-value 對:dict
  • 小練習:請用for循環迭代數列 1-100 并打印出7的倍數
L = []
x = 1
while x > 0 :
    if x >100 :
        break
    L.append(x)
    x = x +1
for i in L:
    if i % 7==0:
        print i

58. 索引迭代

  • 迭代永遠是取出元素本身,而非元素的索引.但是對于有序集合,元素確實是有索引的。有的時候,我們確實想在 for 循環中拿到索引, 這時候就要靠enumerate() 函數:
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> for index, name in enumerate(L):
...     print index, '-', name
... 
0 - Adam
1 - Lisa
2 - Bart
3 - Paul
  • 實際上enumerate() 函數是把list中的每一個元素變成了tuple:
['Adam', 'Lisa', 'Bart', 'Paul']
[(0, 'Adam'), (1, 'Lisa'), (2, 'Bart'), (3, 'Paul')]
  • 迭代的每一個元素實際上是一個tuple:
for t in enumerate(L):
    index = t[0]
    name = t[1]
    print index, '-', name
  • 簡寫為:
for index, name in enumerate(L):
    print index, '-', name
  • 索引迭代也不是真的按索引訪問,而是由 enumerate() 函數自動把每個元素變成 (index, element) 這樣的tuple,再迭代,就同時獲得了索引和元素本身.
  • 小練習:zip()函數可以把兩個 list 變成一個 list:
>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]
  • 小練習:zip()函數可以把兩個 list 變成一個 list:
>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]
  • 需求:在迭代 ['Adam', 'Lisa', 'Bart', 'Paul'] 時,如果我們想打印出名次 - 名字(名次從1開始),請考慮如何在迭代中打印出來。
    提示:考慮使用zip()函數和range()函數:range(1, ?) 可以創建出起始為 1 的數列。
L = ['Adam', 'Lisa', 'Bart', 'Paul']
for index, name in zip(range(1, len(L)+1), L):
    print index, '-', name
    1. 迭代dict的value
  • dict對象本身就是可迭代對象,用 for 循環直接迭代 dict,可以每次拿到dict的一個key,如果迭代value,可以使用values() 方法,這個方法把dict轉換成一個包含所有value的list,這樣,我們迭代的就是 dict的每一個 value。

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
# [85, 95, 59]
for v in d.values():
    print v
# 85
# 95
# 59
  • dict除了values()方法外,還有一個 itervalues() 方法,用 itervalues() 方法替代 values() 方法,迭代效果完全一樣
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
# <dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
    print v
# 85
# 95
# 59
  • 不同之處:
  1. values() 方法實際上把一個 dict 轉換成了包含 value 的list。
  2. 但是 itervalues() 方法不會轉換,它會在迭代過程中依次從 dict 中取出 value,所以 itervalues() 方法比 values() 方法節省了生成 list 所需的內存。
  3. 打印 itervalues() 發現它返回一個 <dictionary-valueiterator> 對象,這說明在Python中,for 循環可作用的迭代對象遠不止 list,tuple,str,unicode,dict等,任何可迭代對象都可以作用于for循環,而內部如何迭代我們通常并不用關心。
  • 小練習:給定一個dict:
    d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
    請計算所有同學的平均分。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }

sum = 0.0
for x in d.itervalues():
    sum = sum +x
print sum/len(d)

60. 迭代dict的key和value

  • items() 方法:items() 方法把dict對象轉換成了包含tuple的list,我們對這個list進行迭代,可以同時獲得key和value:
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> print d.items()
[('Lisa', 85), ('Adam', 95), ('Bart', 59)]
>>> for key, value in d.items():
...     print key, ':', value
... 
Lisa : 85
Adam : 95
Bart : 59
  • iteritems() 方法:iteritems() 不把dict轉換成list,而是在迭代過程中不斷給出 tuple,所以, iteritems() 不占用額外的內存:

  • 小練習:請根據dict:
    d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
    打印出 name : score,最后再打印出平均分 average : score。

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }

sum = 0.0
for k, v in d.iteritems():
    sum = sum + v
    print k,':',v
print 'average', ':', sum/len(d)

61. 生成列表

  • 要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],我們可以用range(1, 11):
>>> range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 生成[1x1, 2x2, 3x3, ..., 10x10]怎么做:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 寫列表生成式時,把要生成的元素 x * x 放到前面,后面跟 for 循環,就可以把list創建出來
  • 小練習:請利用列表生成式生成列表 [1x2, 3x4, 5x6, 7x8, ..., 99x100]
    提示:range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,...]:
print [x*(x+1) for x in range(1,101,2)]

62. 復雜表達式

  • for循環的迭代不僅可以迭代普通的list,還可以迭代dict。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }

可以通過一個復雜的列表生成式把它變成一個 HTML 表格:

tds = ['<tr><td>%s</td><td>%s</td></tr>' % (name, score) for name, score in d.iteritems()]
print '<table>'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'

# 注:字符串可以通過 % 進行格式化,用指定的參數替代 %s。字符串的join()方法可以把一個 list 拼接成一個字符串
<table border="1">
<tr><th>Name</th><th>Score</th><tr>
<tr><td>Lisa</td><td>85</td></tr>
<tr><td>Adam</td><td>95</td></tr>
<tr><td>Bart</td><td>59</td></tr>
</table>
  • 小練習:任務
    在生成的表格中,對于沒有及格的同學,請把分數標記為紅色。提示:紅色可以用 <td style="color:red"> 實現。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
def generate_tr(name, score):
    if score < 60 :
            return '<tr><td>%s</td><td style="color:red">%s</td></tr>' % (name, score)
    return '<tr><td>%s</td><td>%s</td></tr>' % (name, score)

tds = [generate_tr(name, score) for name, score in d.iteritems()]
print '<table border="1">'
print '<tr><th>Name</th><th>Score</th><tr>'
print '\n'.join(tds)
print '</table>'

63. 條件過濾

  • 列表生成式的 for 循環后面還可以加上 if 判斷:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  • 如果我們只想要偶數的平方,不改動 range()的情況下,可以加上 if 來篩選:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
  • 小練習:
    請編寫一個函數,它接受一個 list,然后把list中的所有字符串變成大寫后返回,非字符串元素將被忽略。
    提示:
    1. isinstance(x, str) 可以判斷變量 x 是否是字符串;
    2. 字符串的 upper() 方法可以返回大寫的字母。
def toUppers(L):
    return [x.upper() for x in L if isinstance(x, str)]

print toUppers(['Hello', 'world', 101])

64. 多層表達式

  • for循環可以嵌套,因此,在列表生成式中,也可以用多層 for 循環來生成列表
L = []
for m in 'ABC':
    for n in '123':
        L.append(m + n)
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
  • 小練習:利用 3 層for循環的列表生成式,找出對稱的 3 位數。例如,121 就是對稱數,因為從右到左倒過來還是 121
# 百位的循環從 1-9,十位和個位的循環從 0-9

print [100 * n1 + 10 * n2 + n3 for n1 in range(1, 10) for n2 in range(10) for n3 in range(10) if n1==n3]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一、python 變量和數據類型 1.整數 Python可以處理任意大小的整數,當然包括負整數,在Python程序...
    績重KF閱讀 1,766評論 0 1
  • Python變量和數據類型 數據類型 print語句 注釋 Python的注釋以 # 開頭,后面的文字直到行尾都算...
    Gaolex閱讀 2,838評論 5 55
  • 教程地址:python入門 - 慕課網 安裝python 執行腳本 python官網 安裝程序,并將python....
    竹口小生閱讀 477評論 0 0
  • 001關于做足功課 想要做好一件事情的時候,首先要花時間去了解它的本質,自己先多學習多思考,做好充足的準備,不懂的...
    xiao徐徐1閱讀 269評論 0 0
  • 文化是什么? 人人各有認知。朱里長挖掘的本土文化,在我看來是我們人生重要的傳承。 當我們眾...
    波王爺閱讀 343評論 0 0