2020年9月12日星期六

52 《零基礎入門學習Python》筆記 第052講:像極客一樣去思考

《零基礎入門學習Python》筆記    第052講:像極客一樣去思考


0. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!

大家可能還不知道,在Python的社區裡有句俗話:“Python自己帶著電池(Batteries included)”,什麼意思呢?要從Python的設計哲學說起,Python的設計哲學是:優雅、明確和簡單。因此,Python開發者演變出來的哲學就是,用一種方法,最好是只有一種方法來做一件事。雖然我們常常努力大家多思考,條條大路通羅馬,那是為了訓練大家的發散式思維,但是在正式編程中,如果有完善、並且經過嚴密測試過的模塊可以直接實現,那麼我的建議是使用現成的模塊來工作。
所以Python附帶安裝的有Python標準庫,一般我們說的電池就是Python標準庫中的模塊,這些模塊都極其有用,Python標準庫中包含一般任務所需要的模塊,不過呢,Python標準庫包含的模塊有100多個之多,一個個單獨來講那著實是不科學的,所以這一講,我們將學習如何獨立的來探索模塊。
對於Python來說,學習資料其實一直都在身邊(Python不僅帶著電池,還帶著充電器....),我們這裡給大家分析,遇到問題,我們應該如何去找答案,其實90%的答案你都可以通過我們以下的方式來找到解決的方法。
首先要做的就是打開Python的文檔,IDLE-Help-Python Docs(F1),如圖:
What the huck!!! 都是鳥文啊,我看不懂怎麼辦,不會的話當然是學啊,說實話,對於一個程序員來說,還是需要一定的英語基礎的,因為對於經濟全球化的今天,最新最全的文檔基本上都是鳥文的,所以你一點都不懂英語真的是很被動。不過大家也不要氣餒,對於變成來說,只需要掌握基本的單詞就行。
我們接著講,那這個文檔的基本部分包括哪些呢?
(1)What's new in Python3.5?
介紹了相比Python2.0來說的新的變動。
(2)Tutorial
簡易的Python教程,簡單介紹了Python的語法。
(3)Liberary Reference
Python的整編書,這裡詳細列舉了Python所有內置函數和標準庫的各個模塊的用法,非常詳細,但是,你從頭到尾是看不完的,當做字典來查就可以了。
(4)Inatalling Python Modules
教你如何安裝Python的第三方模塊
(5)Distuributing Python Modules
教你如何發布Python的第三方模塊,你需要知道,Python除了標準庫的幾百個官方模塊之外,還有一個叫做pypi的社區,網站為:https://pypi.python.org/pypi蒐集了全球Python愛好者貢獻出來的模塊,你自己也可以寫一個模塊發佈到pypi社區,分享給全世界。
關於第三方模塊,我將會在後面的筆記中為大家整理,
(6)language reference
討論Python的語法和設計哲學
(7)Python setup and usage
談論Python如何在不同平台上安裝和使用
(8)Python HOWTOs
針對一些特定的主題進行深入並且詳細的探討
(9)Extending and Embedding
介紹如何用C和C++ 來開發Python的擴展模塊,還有開發對應所需要的API
關於用C和C++ 為Python開發擴展,也會在後面的筆記中談到。
(10)FAQs
常見問題解答
另外大家可能經常會看到的就是類似於這個PEP這個詞語
PEP是Python Enhancement Proposals 的縮寫,翻譯過來就是Python增強建議書的意思。它是用來規範與定義Python的各種加強和延伸功能的技術規格,好讓Python開發社區能有共同遵循的依據。
每一個PEP都有一個唯一的編號,這個編號一旦給定就不會再改變。例如,PEP 3000 就是用來定義Python 3.0 的相關技術規格;而PEP 333 則是Python 的Web 應用程序界面WSGI (Web Server Gateway Interface 1.0)的規範。關於PEP 本身的相關規範定義在PEP 1,而PEP 8 則定義了Python 代碼的風格指南。
有關PEP的列表大家可以參考PEP 0 :< https://www.python.org/dev/peps/ >
接下來就來舉個實例,說說我遇到問題是怎麼自救的,前陣子,我們不是舉了一個計時器的例子嗎,後來在第44課的課後作業的最後面,我們說,現實編程中,計時器工具千萬不要自己動手寫,因為有很多未知的因素會影響到你的數據,所以我們建議使用現成的模塊,這個模塊叫做timeit,來對你的代碼來進行計時。假設我們現在不知道timeit 模塊的用法,我應該如何入手呢?
那我們就開始來翻剛才這個文檔了,我們可以使用它的搜索、索引功能,一般給出的第一個都是你需要的
如果你認為快速學習一個模塊都要讀這麼長一篇長篇大論,那你真是too young too simple 了,快速掌握一個模塊的用法,事實上可以使用IDLE 交互界面,首先import 該模塊,然後可以調用__doc_ _屬性,這樣就可以查看到這個模塊的簡介,如圖:
事實上你對於這個方法應該很熟悉了,這跟我們之間講過的函數文檔是一樣的,就是寫在模塊最開頭的那個字符串,這個字符串是帶格式的,我們可以使用print()把這個格式打印出來。會更好看一點:
然後你可能需要知道這個模塊裡面定義了哪些變量,哪些函數,哪些類,你可以用dir() 內置方法把它顯示出來:
  1. >>> dir(timeit)
  2. ['Timer', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_globals', 'default_number', 'default_repeat', 'default_timer', 'dummy_src_name', 'gc', 'itertools', 'main', 'reindent', 'repeat', 'sys', 'template', 'time', 'timeit']
顯示出來的這些並不是所有的名字對我們都有用,所以我們需要過濾一些我們不需要的東西,那你可能留意到__all__這個屬性了,這個屬性其實就是幫助我們完成過濾的過程,我們調用__all__屬性:
  1. >>> timeit.__all__
  2. ['Timer', 'timeit', 'repeat', 'default_timer']
它返回給我們的依然是一個列表,但是相比上面的來說,只有其中的4個成員,如果你有看前面的關於timeit 的文檔的話,你會發現,Timer是一個類,timeit、repeat、 default_timer 是3個接口函數。所以,我們這個__all__ 屬性顯示出來的就是這個模塊可以供外界調用的所有東西。
這裡有兩點需要注意的,首先,不是所有的模塊都有__all__ 屬性,有__all__ 的話,這個屬性裡麵包含的內容就是作者希望外部調用的名字,其它的就是不希望外部調用的了。其次,第二點就是,如果一個模塊設置了__all__ 屬性,那麼使用from '模塊名' import * 語句導入到命名空間的操作,只有__all__ 屬性這裡面的名字才能被導入。例如:
  1. >>> from timeit import *
  2. >>> Timer
  3. <class 'timeit.Timer'>
  4. >>> gc
  5. Traceback (most recent call last):
  6. File "<pyshell#8>", line 1, in <module>
  7. gc
  8. NameError: name 'gc' is not defined
找Timer 就可以找到,但是找gc 就找不到。
但是如果你沒有設置這個__all__ 屬性的話,from '模塊名' import * 就會把所有不以下劃線開頭的名字都導入到當前命名空間,所以,我們建議,你再編寫模塊的時候,對外提供接口函數和類都設置到__all__ 屬性的列表中去,這樣子是比較規範的做法。
還有一個屬性叫做__file__ 屬性,這個屬性是指明了該模塊的源代碼所在的位置
  1. >>> import timeit
  2. >>> timeit.__file__
  3. 'D:\\ProgramFiles\\Anaconda3\\lib\\timeit.py'
我們說過,快速提高編程能力有三大法寶,一個就是不斷地編寫代碼,第二個就是閱讀高手的代碼。
這裡提供了源代碼的路徑,我們就可以去找到它,並通過閱讀它的源代碼,吸取它的精華。
最後我們還可以使用help()函數
在本節課的最後,我需要提一點的就是,timeit這個模塊真的是太有用了,所以呢,我這裡有對應的文檔的中文詳解-> timeit模塊詳解大家有空的話,建議通讀一下。

測試題(筆試,不能上機哦~)

總共16 道題,不上機的情況下答中14 道以下請自覺懺悔!
注:題目雖然簡單,但有陷阱,反正這一講也沒什麼要測試的,就考考大家常識^_^


0. 請問以下代碼會打印什麼內容?

  1. >>> def func():
  2. pass
  3. >>> print(type(func()))
A. <type 'function'>
B. <type 'tuple'>
C. <type 'NoneType'>
D. <type 'type'>
答:C
1. 請問以下代碼會打印什麼內容?
>>> print(type(1J))
A. <type 'unicode'>
B. <type 'int'>
C. <type 'str'>
D. <type 'complex'>
答:D
2. 請問以下代碼會打印什麼內容?
>>> print(type(lambda:None))
A. <type 'NoneType'>
B. <type 'function'>
C. <type 'int'>
D. <type 'tuple'>
答:B
3. 請問以下代碼會打印什麼內容?
  1. >>> a = [1, 2, 3, "FishC", ('a', 'b', 'c'), [], None]
  2. >>> print(len(a))
A. 13
B. 7
C. 6
D. 5
答:B
4. 請問以下代碼會打印什麼內容?
  1. class A:
  2. def __init__(self, x):
  3. x = x + 1
  4. self.v1 = x
  5. class B(A):
  6. def __init__(self, x):
  7. x = x + 1
  8. self.v2 = x
  9. >>> b = B(8)
  10. >>> print("%d %d" % b.v1, b.v2)
A. 9 10
B. 9 9
C. 10 10
D.拋出異常
答:D
5. 請問以下代碼會打印什麼內容?
  1. class A:
  2. def __init__(self, x):
  3. self.x = x
  4. x = 666
  5. >>> a = A()
  6. >>> a = A(888)
  7. >>> a.x
A. 666
B. 888
C. None
D.拋出異常
答:B
6. 請問以下代碼會打印什麼內容?
  1. values = [1, 1, 2, 3, 5]
  2. nums = set(values)
  3. def checkit(num):
  4. if num in nums:
  5. return True
  6. else:
  7. return False
  8. for i in filter(checkit, values):
  9. print(i, end=' ')
A. 1 2 3 5
B. 1 1 2 3 5
C. 1 2 3 4 3 2 1
D.拋出異常
答:B
7. 請問以下代碼會打印什麼內容?
  1. values = [1, 1, 2, 3, 5]
  2. def transform(num):
  3. return num ** 2
  4. for i in map(transform, values):
  5. print(i, end=' ')
A. 1 1 4 9 25
B. 1 1 2 3 5
C. 0.5 0.5 1 1.5 2.5
D. 2 2 4 6 10
答:A
8. 請問以下代碼會打印什麼內容?
  1. class A:
  2. def __init__(self, x):
  3. self.x = x
  4. a = A(100)
  5. a.__dict__['y'] = 50
  6. print(a.y + len(a.__dict__))
A. 2
B. 50
C. 51
D. 52
答:D
9. 請問以下代碼會打印什麼內容?
  1. class A:
  2. def __init__(self):
  3. pass
  4. def get(self):
  5. print(__name__)
  6. >>> a = A()
  7. >>> a.get()
A. A
B. a
C. __main__
D. _A__a
答:C
10. 請問以下代碼會打印什麼內容?
  1. country_counter = {}
  2. def addone(country):
  3. if country in country_counter:
  4. country_counter[country] += 1
  5. else:
  6. country_counter[country] = 1
  7. addone('China')
  8. addone('Japan')
  9. addone('China')
  10. addone("American")
  11. print(len(country_counter))
A. 0
B. 1
C. 2
D. 3
答:D
11.請問以下代碼會打印什麼內容?
  1. dict1 = {}
  2. dict1[1] = 1
  3. dict1['1'] = 2
  4. dict1[1.0] = 3
  5. result = 0
  6. for each in dict1:
  7. result += dict1[each]
  8. print(result)
A. 2
B. 3
C. 5
D. 6
答:C
12. 請問以下代碼會打印什麼內容?
  1. def dostuff(param1, *param2):
  2. print type(param2)
  3. dostuff('apples', 'bananas', 'cherry', 'dates')
A. <type 'int'>
B. <type 'str'>
C. <type 'tuple'>
D. <type 'dict'>
答:C
13. 請問以下代碼會打印什麼內容?
  1. class A:
  2. def __init__(self, a, b, c):
  3. self.x = a + b + c
  4. a = A(1,2,3)
  5. b = getattr(a, 'x')
  6. setattr(a, 'x', b+1)
  7. print a.x
A. 1
B. 2
C. 6
D. 7
答:D
14. 請問以下代碼會打印什麼內容?
  1. list1 = [1, 2]
  2. list2 = [3, 4]
  3. dict1 = {'1':list1, '2':list2}
  4. dict2 = dict1.copy()
  5. dict1['1'][0] = 5
  6. result = dict1['1'][0] + dict2['1'][0]
  7. print(result)
A. 5
B. 6
C. 8
D. 10
答:D
15. 請問以下代碼會打印什麼內容?
  1. import copy
  2. list1 = [1, 2]
  3. list2 = [3, 4]
  4. dict1 = {'1':list1, '2':list2}
  5. dict2 = copy.deepcopy(dict1)
  6. dict1['1'][0] = 5
  7. result = dict1['1'][0] + dict2['1'][0]
  8. print(result)
A. 5
B. 6
C. 8
D. 10
答:B

0 留言:

發佈留言