參考資料地址:https://github.com/LenKiMo/byte-of-python(中文版)
https://github.com/swaroopch/byte-of-python(英文版)
https://python.swaroopch.com/(英文版)
注意點:
1. Python特點:解釋性語言(無需編譯成二進制碼,直接源碼->字節碼->電腦語言)、強面向對象 //字節碼文件以.pyc為擴展名,獨立於運行平台
2. 變量:無需聲明或定義數據類型;沒有long和char類型
3. 格式化方法:format()函數
4. 換行連接
- 顯示行連接:利用"\"連接多行 //后面立即接換行
- 隱式行連接:以括號開始的多行
5. Python 對塊使用縮進,不使用大括號,同一組語句(塊)縮進必須相同 //建議統一用四個空格進行縮進
6. 運算符:整除為“//”
7. 控制流:Python不存在switch語句;while和for語句可以擁有else子句
8. 函數
(1)函數參數:
- 定義函數時給定的名稱稱作“形參”,調用函數時提供給函數的值稱作“實參”
- 默認參數值:在定義時進行賦值 //有默認參數值的參數必須位於參數列表的末尾
- 關鍵字參數:使用命名(關鍵字)而非位置來指定函數中的參數 //優點:無需考慮參數順序;僅需對部分指定參數進行賦值,其他的參數使用默認值
- 可變參數(參數數量是可變的):def func(param1, *param2, **param3),如:
1 def total(a=5, *numbers, **phonebook): 2 print('a', a) 3 #遍歷元組中的所有項目 4 for single_item in numbers: 5 print('single_item', single_item) 6 #遍歷字典中的所有項目 7 for first_part, second_part in phonebook.items(): 8 print(first_part,second_part) 9 print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))
其中,*param2參數表明所有未指定的位置參數將構成名稱為“param2”的元組(Tuple),而**param3則表明所有未指定的關鍵字參數將構成名字為“param3”的字典(dictionary)
(2)變量作用域
局部變量:變量的作用域為被定義的塊,如函數內變量
全局變量:使用global語句進行聲明后再使用
(3)文檔字符串(DocStrings):用於在函數定義開始對程序功能進行說明,如 def print_max(x, y):
2 '''Prints the maximum of two numbers.打印兩個數值中的最大數。 3 The two values must be integers.這兩個數都應該是整數''' 4 # 如果可能,將其轉換至整數類型 5 x = int(x) 6 y = int(y) 7 if x > y: 8 print(x, 'is maximum') 9 else: 10 print(y, 'is maximum') 11 12 print_max(3, 5) 13 print(print_max.__doc__) #使用函數對象的__doc__屬性 ,也可使用help函數:help(print_max),或者pydoc命令
注:文檔字符串一般約定為一串多行字符串,其中第一行以某一大寫字母開始,以句號結束。第二行為空行,后跟的第三行開始是任何詳細的解釋說明。
9. 模塊(以.py為后綴名,包含函數與變量的文件)
(1)導入模塊
- (建議)利用import語句導入模塊:如import sys //Python從當前程序目錄和sys.path變量所提供的目錄進行模塊搜索;sys.path的值與環境變量PYTHONPATH等同
- 利用from...import...語句 //應避免使用,防止程序中出現命名沖突
- 利用from...import *導入模塊中所有公共名稱 //避免使用
(2)常用模塊
import os, time
- print(os.getcwd()) //輸出當前目錄
- os.sep //當前操作系統所采用的分隔符(便於程序可移植),Linux為“/”,Windows為“\\”(轉義\),Mac為“:”
- os.path.exists() //判斷目錄路徑是否存在
- os.mkdir() //創建目錄
- time.strftime() //將當前日期轉化為字符串,可以設置顯示格式
- os.system() //使命令從系統中運行,如shell
- os.remove() //刪除文件
(3)模塊的名稱__name__屬性,用於確定所在模塊的名稱,如利用__name__確定模塊是獨立運行還是被導入進來運行:
1 if __name__ == '__main__': 2 print('This program is being run by itself') 3 else: 4 print('I am being imported from another module')
注:每一個 Python 模塊都定義了它的 __name__ 屬性。如果它與 __main__ 屬性相同則代表這一模塊是由用戶獨立運行的
(4)dir()函數 //內置函數返回由對象所定義的名稱列表,如果參數是模塊名稱,函數將返回這一指定模塊的名稱列表(函數、類、變量);如果沒有提供參數,函數將返回當前模塊的名稱列表。 //del語句用於刪除變量或名稱,如del a
(5)包(Packages):組織模塊的層次結構 //from 包.模塊 import ... 需要包文件夾位於python的搜索路徑——環境變量PYTHONPATH中
包是指一個包含模塊與一個特殊的__init__.py文件的文件夾 //__init__.py表明這一文件夾包含Python模塊
#創建一個名為“world”的包,其中還包含着 “asia”、“africa”等其它子包
#同時這些子包都包含了諸如“india”、“madagascar”等模塊。
1 - <some folder present in the sys.path>/ 2 - world/ 3 - __init__.py 4 - asia/ 5 - __init__.py 6 - india/ 7 - __init__.py 8 - foo.py 9 - africa/ 10 - __init__.py 11 - madagascar/ 12 - __init__.py 13 - bar.py
10. 數據結構
(1)列表(可變數據類型):利用方括號定義,如shoplist = ['apple', 'mango', 'carrot', 'banana'] //help(list)查看更多細節
(2)元組(不可變數據類型):將多個對象保存在一起,建議利用圓括號定義,如zoo = ('python', 'elephant', 'penguin'),單項目元組 singleton = (2, ) //help(tuple)
(3)字典(可變數據類型):存儲“鍵-值”對(類似地址簿),利用花括號定義,如d = {key : value1 , key2 : value2},其中鍵必須是不可變的對象(如字符串),且字典中不同“鍵-值”對是無序的 //help(dict)
(4)序列:列表、元組和字符串均可以看作序列(Sequence)的某種表現形式,序列的主要功能是資格測試(in和not in表達式)和索引操作(從0開始)
(5)集合:簡單對象的無序集合,如bri = set(['brazil', 'russia', 'india']) //help(set)
(6)利用變量創建對象,變量僅僅是對對象的一個引用(refer),即變量名僅指向對象在內存中的地址,也被視為將名稱綁定(Binding)到對象上;示例代碼如下:
1 print('Simple Assignment') 2 shoplist = ['apple', 'mango', 'carrot', 'banana'] 3 # mylist 只是指向同一對象的另一種名稱 4 mylist = shoplist #簡單賦值,不創建副本 5 # 我購買了第一項項目,所以我將其從列表中刪除 6 del shoplist[0] 7 print('shoplist is', shoplist) 8 print('mylist is', mylist) 9 # 注意到 shoplist 和 mylist 二者都 10 # 打印出了其中都沒有 apple 的同樣的列表,以此我們確認 11 # 它們指向的是同一個對象 12 print('Copy by making a full slice') 13 # 通過生成一份完整的切片制作一份列表的副本 14 mylist = shoplist[:] #切片操作創建新的副本 15 # 刪除第一個項目 16 del mylist[0] 17 print('shoplist is', shoplist) 18 print('mylist is', mylist) 19 # 注意到現在兩份列表已出現不同
注:列表等復雜對象的賦值語句只是對同一對象的“查閱”,如果需要創建副本,必須使用切片操作制作副本
11. 面向對象編程
對象(object)是類(class)的實例(instance),包含兩種屬性(attribute):字段(變量)、方法(函數)
(1)類方法和普通函數的區別:類方法的第一個參數必須為self(引用對象本身)且不可缺省,但是調用時無需顯式賦值 //相當於C++中的指針以及Java與C#中的this指針
(2)__init__()方法:進行對象初始化,且無需顯式調用 //前后均為雙下划線
1 class Person: 2 def __init__(self, name): #無需顯式調用 3 self.name = name 4 def say_hi(self): 5 print('Hello, my name is', self.name) 6 7 p = Person('Swaroop') 8 p.say_hi() 9 # 前面兩行同時也能寫作 10 # Person('Swaroop').say_hi()
(3)類變量和對象變量:類變量為該類的所有實例共享,對象變量為類的實例對象獨立擁有
1 # coding=UTF-8 2 class Robot: 3 """表示有一個帶有名字的機器人。""" 4 # 一個類變量,用來計數機器人的數量 5 population = 0 6 def __init__(self, name): 7 """初始化數據""" 8 self.name = name 9 print("(Initializing {})".format(self.name)) 10 # 當有人被創建時,機器人 11 # 將會增加人口數量 12 Robot.population += 1 #等同於self.__class__.population += 1 13 14 def die(self): 15 """我掛了。""" 16 print("{} is being destroyed!".format(self.name)) 17 Robot.population -= 1 18 if Robot.population == 0: 19 print("{} was the last one.".format(self.name)) 20 else: 21 print("There are still {:d} robots working.".format(Robot.population)) 22 23 def say_hi(self): 24 """來自機器人的誠摯問候 25 沒問題,你做得到。""" 26 print("Greetings, my masters call me {}.".format(self.name)) 27 28 @classmethod #類方法,使用裝飾器Decorator將how_many標記為類方法 29 def how_many(cls): 30 """打印出當前的人口數量""" 31 print("We have {:d} robots.".format(cls.population)) 32 33 droid1 = Robot("R2-D2") 34 droid1.say_hi() 35 Robot.how_many() 36 37 droid2 = Robot("C-3PO") 38 droid2.say_hi() 39 Robot.how_many() 40 41 print("\nRobots can do some work here.\n") 42 print("Robots have finished their work. So let's destroy them.") 43 droid1.die() 44 droid2.die() 45 46 Robot.how_many()
注:
- 所有的類成員都是公開的,如果使用數據成員並在其名字中使用雙下划線作為前綴,形成諸如 __privatevar這樣的形式,Python會使用名稱調整來使其有效地成為一個私有變量;因此,建議遵循如下約定:任何在類或對象之中使用的變量其命名應以下划線開頭,其它所有非此格式的名稱都將是公開的,並可以為其它任何類或對象所使用。
- 裝飾器(Decorators)是應用包裝函數的快捷方式,有助於將某一功能與一些代碼一遍又一遍地“包裝”
- python裝飾器的通俗理解:https://blog.csdn.net/u013471155/article/details/68960244
(4)繼承:基類/超類、派生類/子類、多態性(子類型對象可以看作父類的實例)
1 # coding=UTF-8 2 class SchoolMember: 3 '''代表任何學校里的成員。''' 4 def __init__(self, name, age): 5 self.name = name 6 self.age = age 7 print('(Initialized SchoolMember: {})'.format(self.name)) 8 9 def tell(self): 10 '''告訴我有關我的細節。''' 11 print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ") 12 13 class Teacher(SchoolMember): #繼承,參數為包含基類名稱的元組 14 '''代表一位老師。''' 15 def __init__(self, name, age, salary): 16 SchoolMember.__init__(self, name, age) #子類定義__init__的情況下需要顯式調用父類構造函數__init__ 17 self.salary = salary 18 print('(Initialized Teacher: {})'.format(self.name)) 19 20 def tell(self): 21 SchoolMember.tell(self) #子類對象作為父類方法的實例參數 22 print('Salary: "{:d}"'.format(self.salary)) 23 24 class Student(SchoolMember): 25 '''代表一位學生。''' 26 def __init__(self, name, age, marks): 27 SchoolMember.__init__(self, name, age) 28 self.marks = marks 29 print('(Initialized Student: {})'.format(self.name)) 30 31 def tell(self): 32 SchoolMember.tell(self) 33 print('Marks: "{:d}"'.format(self.marks)) 34 35 t = Teacher('Mrs. Shrividya', 40, 30000) 36 s = Student('Swaroop', 25, 75) 37 # 打印一行空白行 38 print() 39 40 members = [t, s] 41 for member in members: 42 # 對全體師生工作 43 member.tell()
12. 輸入與輸出
(1)用戶輸入內容:input()函數
(2)文件:創建(open)一個屬於file類的對象並適當使用它的read、readline、write方法
1 poem = '''\ 2 Programming is fun 3 When the work is done 4 if you wanna make your work also fun: 5 use Python! 6 ''' 7 8 # 打開文件以編輯('w'riting) 9 f = open('poem.txt', 'w') 10 # 向文件中編寫文本 11 f.write(poem) 12 # 關閉文件,保證內容已經被寫入到文件 13 f.close() 14 15 # 如果沒有特別指定, 16 # 將假定啟用默認的閱讀('r'ead)模式 17 f = open('poem.txt') 18 while True: 19 line = f.readline() 20 # 零長度指示 EOF 21 if len(line) == 0: 22 break 23 # 每行(`line`)的末尾 24 # 都已經有了換行符 25 #因為它是從一個文件中進行讀取的 26 print(line, end='') 27 # 關閉文件 28 f.close()
(3)pickle標准模塊:將任何純Python對象存儲到一個文件中,並在稍后將其取回
1 import pickle 2 3 # The name of the file where we will store the object 4 shoplistfile = 'shoplist.data' 5 # The list of things to buy 6 shoplist = ['apple', 'mango', 'carrot'] 7 8 # Write to the file 9 f = open(shoplistfile, 'wb') 10 # Dump the object to a file 11 pickle.dump(shoplist, f) #封裝 12 f.close() 13 14 # Destroy the shoplist variable 15 del shoplist 16 17 # Read back from the storage 18 f = open(shoplistfile, 'rb') 19 # Load the object from the file 20 storedlist = pickle.load(f) #拆封 21 print(storedlist)
13. 異常
(1)try..except...語句:檢查語句,並根據異常類型進行相應的處理
1 try: 2 text = input('Enter something --> ') #需要檢查的語句塊 3 except EOFError: #捕獲異常類型 4 print('Why did you do an EOF on me?') 5 except KeyboardInterrupt: 6 print('You cancelled the operation.') 7 else: 8 print('You entered {}'.format(text))
(2)raise語句:主動拋出異常對象,引發異常處理
1 # encoding=UTF-8 2 3 class ShortInputException(Exception): #繼承自Exception類 4 '''一個由用戶定義的異常類''' 5 def __init__(self, length, atleast): 6 Exception.__init__(self) 7 self.length = length 8 self.atleast = atleast 9 10 try: 11 text = input('Enter something --> ') 12 if len(text) < 3: 13 raise ShortInputException(len(text), 3) #拋出自定義異常 14 # 其他工作能在此處繼續正常運行 15 except EOFError: 16 print('Why did you do an EOF on me?') 17 except ShortInputException as ex: #捕獲自定義異常 18 print(('ShortInputException: The input was ' + '{0} long, expected at least {1}').format(ex.length, ex.atleast)) 19 else: 20 print('No exception was raised.')
(3)try...finally...:確保finally出的語句塊被執行,例如確保文件對象的正確關閉
1 import sys 2 import time 3 4 f = None 5 try: 6 f = open("poem.txt") 7 # 我們常用的文件閱讀風格 8 while True: 9 line = f.readline() 10 if len(line) == 0: 11 break 12 print(line, end='') 13 sys.stdout.flush() #將輸出立即打印到屏幕 14 print("Press ctrl+c now") 15 # 為了確保它能運行一段時間 16 time.sleep(2) #休眠兩秒 17 except IOError: 18 print("Could not find file poem.txt") 19 except KeyboardInterrupt: 20 print("!! You cancelled the reading from the file.") 21 finally: #該部分子句一定會執行 22 if f: 23 f.close() 24 print("(Cleaning up: Closed the file)")
注:確保文件關閉的快捷方式——with語句(避免顯示調用try...finally語句)
#with語句會獲取由open語句返回的對象‘thefile’,並在代碼塊開始前調用thefile.__enter__函數,在代碼塊執行完畢之后調用thefile.__exit__
1 with open("poem.txt") as f: #將關閉文件的操作交由with open來自動完成(__exit__方法) 2 for line in f: 3 print(line, end='')
14. 標准庫(https://docs.python.org/3/library/)
(1)sys模塊:
sys.argv:命令行參數,如查看Python軟件版本sys.version_info
(2)logging日志模塊:用於記錄信息
(3)os模塊:用於和操作系統交互
(4)platform模塊:用於獲取平台(操作系統)的信息
1 import os 2 import platform 3 import logging 4 5 if platform.platform().startswith('Windows'): #返回正在使用的操作系統 6 logging_file = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'), 'test.log') 7 else: 8 logging_file = os.path.join(os.getenv('HOME'), 'test.log') 9 10 print("Logging to", logging_file) 11 logging.basicConfig( 12 level=logging.DEBUG, 13 format='%(asctime)s : %(levelname)s : %(message)s', 14 filename=logging_file, 15 filemode='w', 16 ) 17 18 logging.debug("Start of the program") 19 logging.info("Doing something") 20 logging.warning("Dying now")
15. 更多。。。(建議參考PDF原文)
(1)函數返回多個值:傳遞元組
(2)特殊方法:用來模擬內置類型的某些行為
- __init__(self, ...):初始化,在新創建的對象被返回准備使用時被調用
- __del__(self):在對象被刪除之前調用(它的使用時機不可預測,所以避免使用它)
- __str__(self):使用print函數時,或str()被使用時被調用
- __lt__(self, other):當小於運算符(<)被使用時被調用。類似地,其它所有運算符(+、> 等等)也存在相應的特殊方法
- __getitem__(self, key):使用x[key]索引操作時會被調用
- __len__(self):針對序列對象使用內置len()函數時會被調用
(3)單語句塊:如果語句塊只包括單獨的一句語句時,可以在同一行指定它,如條件語句和循環語句,如if flag: print('Yes')
注:單語句塊是在原地立即執行,不會被看作單獨的語句塊,但是會影響程序整體的工整性,不建議使用
(4)lambda語句:可以創建一個新的函數對象;從本質上說, lambda 需要一個參數,后跟一個表達式作為函數體,這一表達式執行的值將作為這個新函數的返回值
1 points = [{'x': 2, 'y': 3}, {'x': 4, 'y': 1}] 2 points.sort(key=lambda i: i['y']) #調用list的sort方法,通過獲得一個key參數,用以決定列表的排序方式 3 print(points)
注:lambda表達式用於實現僅使用一次的簡單函數,而無需編寫獨立的def塊
(4)列表推導:用於從一份現有的列表中得到一份新列表,可避免顯式調用循環過程,減少代碼量
1 listone = [2, 3, 4] 2 listtwo = [2*i for i in listone if i > 2] 3 print(listtwo)
(5)assert語句:用於斷言(判斷)某事是真的;斷言失敗時,會拋出錯誤AssertionError
1 import numpy as np 2 a = np.random.randn((5,1)) 3 assert(a.shape = (5,1)) #保證數組a的大小是正確的
注:在大多數情況下,明智地選用 assert 語句好過捕獲異常,也好過定位問題或向用戶顯示錯誤信息然后退出