C/C++与Python的语法差异
PYTHON語言,一切皆對象!
究竟何謂對象?不同的編程語言以不同的方式定義“對象”。某些語言中,它意味著所有對象必須有屬性和方法;另一些語言中,它意味著所有的對象都可以子類化。
在Python中,定義是松散的,某些對象既沒有屬性也沒有方法,而且不是所有的對象都可以子類化。
1 但是Python的萬物皆對象從感性上可以解釋為:Python 中的一切都可以賦值給變量或者作為參數傳遞給函數。
Python 的所有對象都有三個特性:
- 身份:每個對象都有一個唯一的身份標識自己,任何對象的身份都可以使用內建函數 id() 來得到,可以簡單的認為這個值是該對象的內存地址。
- 類型:對象的類型決定了對象可以保存什么類型的值,有哪些屬性和方法,可以進行哪些操作,遵循怎樣的規則。可以使用內建函數 type() 來查看對象的類型。
- 值:對象所表示的數據
“身份”、"類型"和"值"在所有對象創建時被賦值。如果對象支持更新操作,則它的值是可變的,否則為只讀(數字、字符串、元組等均不可變)。只要對象還存在,這三個特性就一直存在。
對象的屬性 :大部分 Python 對象有屬性、值或方法,使用句點(.)標記法來訪問屬性。最常見的屬性是函數和方法,一些 Python 對象也有數據屬性,如:類、模塊、文件等
2 Python 解釋型語言
所謂編譯執行就是源代碼經過編譯器編譯處理,生成目標機器碼,就是機器能直接運行的二進制代碼,下次運行時無需重新編譯。不過它是針對特定CPU體系的,這些目標代碼只能在特定平臺執行,如果這個程序需要在另外一種 CPU 上面運行,這個代碼就必須重新編譯。它不具備可移植性,但是執行速度快,C、C++這類語言屬于編譯型語言。
而解釋型語言是在代碼運行期間逐行翻譯成目標機器碼,下次執行時,還是需要逐行解釋,我們可以簡單認為 Java、Python 都是解釋型語言。
-
編譯型相當于廚師直接做好一桌子菜,顧客來了直接開吃,而解釋型就像吃火鍋,廚師把菜洗好,顧客需要自己動手邊煮邊吃。
-
效率上來說解釋型語言自然比不過編譯型語言,當然也不是絕對了,像 JIT 的效率就很高。
以上是對編譯型語言和解釋型語言的一個簡單粗暴的區分,但是 Python(這里主要是指CPython)并不是嚴格的解釋型語言;
因為 Python 代碼在運行前,會先編譯(翻譯)成中間代碼,每個 .py 文件將被換轉成 .pyc 文件,.pyc 就是一種字節碼文件,它是與平臺無關的中間代碼,不管你放在 Windows 還是 Linux 平臺都可以執行,運行時將由虛擬機逐行把字節碼翻譯成目標代碼。
我們安裝Python 時候,會有一個 Python.exe 文件,它就是 Python 解釋器,你寫的每一行 Python 代碼都是由它負責執行,解釋器由一個編譯器和一個虛擬機構成,編譯器負責將源代碼轉換成字節碼文件,而虛擬機負責執行字節碼,所以,解釋型語言其實也有編譯過程,只不過這個編譯過程并不是直接生成目標代碼,而是中間代碼(字節碼),然后再通過虛擬機來逐行解釋執行字節碼。
總結
- Python代碼首先會編譯一個字節碼文件,再由虛擬機逐行解釋,把每一行字節碼代碼翻譯成目標指令給CPU執行。
Python內部執行過程
- 一、編譯過程概述
當我們執行Python代碼的時候,在Python解釋器用四個過程“拆解”我們的代碼,最終被CPU執行返回給用戶。
(1)首先當用戶鍵入代碼交給Python處理的時候會先進行詞法分析,例如用戶鍵入關鍵字或者當輸入關鍵字有誤時,都會被詞法分析所觸發,不正確的代碼將不會被執行。
(2)下一步Python會進行語法分析,例如當"for i in test:"中,test后面的冒號如果被寫為其他符號,代碼依舊不會被執行。
(3)下面進入最關鍵的過程,在執行Python前,Python會生成.pyc文件,這個文件就是字節碼,如果我們不小心修改了字節碼,Python下次重新編譯該程序時會和其上次生成的字節碼文件進行比較,如果不匹配則會將被修改過的字節碼文件進行覆蓋,以確保每次編譯后字節碼的準確性。
那么什么是字節碼?字節碼在Python虛擬機程序里對應的是PyCodeObject對象。.pyc文件是字節碼在磁盤上的表現形式。簡單來說就是在編譯代碼的過程中,首先會將代碼中的函數、類等對象分類處理,然后生成字節碼文件。有了字節碼文件,CPU可以直接識別字節碼文件進行處理,接著Python就可執行了。
二、過程圖解
二、過程圖解
http://www.opython.com/1355.html
Python程序運行時,就像上面的例子一樣,先將源代碼完整的進行轉換,編譯成更有效率的字節碼,保存成后綴為“.pyc”的字節碼文件,然后,翻譯器再通過這個文件一句一句的翻譯為機器語言去執行。
3 Python 使用 LEGB 的順序來查找一個符號對應的對象
locals -> enclosing function -> globals -> builtins
-
locals,當前所在命名空間(如函數、模塊),函數的參數也屬于命名空間內的變量
-
enclosing,外部嵌套函數的命名空間(閉包中常見)
- globals,全局變量,函數定義所在模塊的命名空間
- builtins,內置模塊的命名空間。Python 在啟動的時候會自動為我們載入很多內置的函數、類,比如 dict,list,type,print,這些都位于 builtins 模塊中,可以使用 dir(builtins) 來查看。這也是為什么我們在沒有 import 任何模塊的情況下,就能使用這么多豐富的函數和功能了。
介紹完命名空間,就能理解 print(a) 這行代碼輸出的結果為什么是 a string 了。
零、類型
PYTHON 內置對象:
- PYTHON中,不需要事先聲明變量名及其類型,直接賦值即可創建各種類型的變量。
- PYTHON屬于強類型編程語言,使用變量時,需要程序員自己確定所進行的運算是否合適,以免出現異常或者意料之外的結果。
- PYTHON是一種動態類型語言,變量的類型可以隨時變化。
| Number(數字) | 3.14159, 1234, 999L 3+4j | 不可變對象,修改變量值,不是真的修改變量內存地址的存儲數值,而是把值放到內存中,然后修改變量,使其指向新的內存地址 |
| String(字符串) | ‘spam’, “guido’s” | 不可變有序序列,使用單引號,雙引號,三引號進行界定,并可互相嵌套,表示復雜的字符串,(1)采用%或則format(推薦)方式進行格式化,把其他類型的內容轉換成需要的字符串,(2)采用轉義字符表示對應的符號\n,\t,\r……,(3)采用r或者R表示原字符串 |
| List(列表) | [1,[2, ‘Three’],4] | 可變有序序列 (1)是包含若干元素的有序連續內存空間,(2)當列表增加或者刪除元素時,列表對象自動進行內存的擴展或收縮;(3)支持切片操作,不會因為下標越界而拋出異常,代碼具有更強的健壯性。(4)切片操作可以實現原地修改列表內容,增加,刪減,修改,查找,替換等操作,并且不影響列表對象的內存地址。(5)切片返回的是淺復制,與列表對象的直接賦值(引用)是不一樣的。(6)支持列表推導式,用[ ]括起來的列表推導式,eg:alist=[x*x for x in range(10)] (7)深拷貝,需要用特定函數,實現深層(嵌套結構)的拷貝。 |
| Dictionary(字典) | {‘food’:‘spam’, ‘taste’:‘yum’} | 可變無序序列(1)包含:鍵和值,(2) |
| Set(集合) | {‘food’,‘taste’} | 可變無序序列 |
| Tuple(元組) | (1,‘spam’,4,‘U’) | 不可變有序序列(1)一旦創建,不可以修改,增加和刪除,(2)元組內如包含可變元素列表,可對該元素修改,(3)元組的處理速度比列表快,如只是遍歷或者其他類似用途,建議采用元組,(4)擴展: 用( )括起來的生成器推導式,eg:atuple= (x*x for x in range(10)) 其結果為生成器對象! |
| File(文件) | text=open(‘egges’,‘r’).read() |
C/C++數據類型:
C++ 為程序員提供了種類豐富的內置數據類型和用戶自定義的數據類型。下表列出了七種基本的 C++ 數據類型:
| 布爾型 | bool |
| 字符型 | char |
| 整型 | int |
| 浮點型 | float |
| 雙浮點型 | double |
| 無類型 | void |
| 寬字符型 | wchar_t |
一、基本語法
1、程序塊語法方面:
c/c++中用一對“{}”將多段語句括起來,表示一個程序塊,并以右大括號表明程序塊結束
for(i=0;i<n;i++) {cout<<a[i];j+=1; }Python中用縮進方式表明某幾句語句為同一程序段
for i in n:print(a)j+=12、對for循環的使用
c/c++中用如下形式:for(i=0;i<n;i++){語句},主要是以某一可控值(如:n)控制循環的進行
Python中采用如下形式:for i in range:,采用序列的方式控制循環的進行
3、python的隨機數產生
python的隨機數產生函數random.randrange()如果傳入兩個參數,就會產生從低端點(包含)到高端點(不包含)之間的隨機數
4、Python的不變性
python中的字符串中的元素不能通過直接賦值修改
如:
word="game"word[0]="l"這段代碼就是錯的
而在c/c++中則可以直接通過這種方式對字符串進行修改
需要理解的是,在python中對字符串變量重新賦值并不是改變了字符串,而是重新構造了字符串:test=“keyword”
這種不變性同樣適用于元組(c/c++中的數組):test=(“keyword1”,“keyword2”,…)
如果需要對組合元素序列進行修改,可以使用列表或字典,這兩種存儲方式可以對其中的元素成員進行修改操作:test=[“keyword1”,“keyword2”,…]
5、python不需要對變量的類型進行申明,直接定義,且初始化只需要對變量賦空值即可,
如:cout=“”;
6、python可以用負值進行位置編號:
正值的編號是從左向右依次從0開始編號
負值的編號是從右向左一次從-1開始編號
7、python引入了字符串切片的概念:
采用a[start:finish]表示在字符串a中從編號start開始到編號finish之間的片段
切片概念同樣適用于元組、列表和字典
8、Python中的列表和c/c++中的數組
Python中的列表可以利用切片的概念對列表進行整體賦值,如:inventory[4:6]=[“orb of future telling”],每個元素間只需空格隔開;
Python編譯器自帶數據訪問的越界檢查
Python的列表可以進行整體輸入輸出
python可以單個刪除某個列表元素,也可以利用切片刪除連續的多個元素
>>> test=["word","letter","honest","yes"]>>> print(test)['word', 'letter', 'honest', 'yes']>>> del test[2]>>> print(test)['word', 'letter', 'yes']>>>c/c++中的數組任何情況下都不允許進行整體賦值(除非重新定義數組),且不會對數組進行越界檢查
c/c++的數組不能整體輸入輸出,刪除元素時也只能進行覆蓋操作
9、Python中支持嵌套序列
如:可以再列表中包含其他列表或元組
對嵌套元素訪問時,可以先把列表中的元組賦給另一個值,從另一個值訪問被包含元組的成員值
>>> scores=[("a",100),("b",200)] >>> score=scores[0] >>> print(score) ('a', 100) >>> print(score[0]) a >>>也可以直接用類似c/c++中二維數組的形式進行訪問:先獲得第一層序列的值,然后再獲取該值第二層序列值(專業名詞叫多重索引)
>>> score=[("a",100),("b",200)]>>> print(score[0][0])a>>> print(score[0][1])100>>>10、任何類型的序列都可以解包,分別把序列中的各個元素賦值給其他變量,這個是c/c++不具有的性質,使得Python有了更大的靈活性
***元組、列表、字典都是序列
>>> test=[("a",100),("b",400)]>>> test1,test2=test>>> print(test1)('a', 100)>>> print(test2)('b', 400)>>>11、Python中對值的存儲采用引用的方式,變量本身并不存儲值,
如:test=“python”,只是在內存中存儲這個字符串,用test作為名字指向這個字符串,對test的任何操作實際上都是對字符串本身的操作,這一點與c/c++不同,實例如下:
>>> test=["python","java"]>>> print(test)['python', 'java']>>> test1=test>>> print(test1)['python', 'java']>>> test1[0]="c/c++">>> print(test1)['c/c++', 'java']>>> print(test)['c/c++', 'java']>>>以上例子說明,所謂的變量其實就是一個引用時使用的名字,對這個名字的任何操作,其實都是對他指向的實體內容的操作
但可以通過切片取得原來一個實體的副本,這樣對副本的修改就不會影響到原來的實體,因為切片取得的永遠都是一個副本
>>> test=["python","java"]>>> print(test)['python', 'java']>>> test1=test[:]>>> test1[0]="c/c++">>> print(test1)['c/c++', 'java']>>> print(test)['python', 'java']>>>如以上結果,對test1的修改并沒有影響到test所指的值,因為test1是從test切片過來的“副本”
12、python中的靜態方法(方法前加入“@stasticmethod”修飾符)盡量不要和其他方法在命名上相同,因為python中在調用時,會優先調用靜態方法,如果靜態方法和其他方法名稱相同,則在運行時會自動忽略對其他方法的調用
這一點上與c++的函數重載有所不同
13、C++中,外部函數對類私有成員的訪問是絕對禁止的
但Python中對私有特性的訪問卻不是絕對禁止的,在私有特性前加入“—類名”,即可實現對其的訪問,如:
同理,私有方法也是這樣的
***同時,Python中提出了一種對特性進行控制的概念,即,對特定的特性修改時做部分限制,只需要在能訪問該特性的方法前加入“@property”修飾符,將它設置為屬性即可,
并且Python中可以為特性單獨設置屬性值,格式為:“@+屬性的名稱+“.”+setter”
14、python中可以直接在變量后攜帶兩個字符串,用來創建新的字符串:
>>> foo="hello""world" >>> foo 'helloworld'15、python中引入了原始字符串操作符r/R,
用來把常用字符串按照字面意思來使用,而不考慮其轉義特性:
>>> f=open("e:\readme.txt","r")Traceback (most recent call last):File "<pyshell#14>", line 1, in <module>f=open("e:\readme.txt","r") IOError: [Errno 22] invalid mode ('r') or filename: 'e:\readme.txt' >>> f=open("e:\\readme.txt","r") >>> f=open(r"e:\readme.txt","r")以上的例子可以看到使用原始字符串操作符可以用直面語義使用字符串,相對原始的語法規定(包括c/c++)使用起來更為方便
16、python中,字符串不是以"NULL"或“\0”結束的,
在對字符串賦值時,不需要考慮字符串結束符的問題,這一點與c/c++有所不同,避免了c/c++由此造成的內存越界。
17、列表推導式
用[ ]括起來的列表推導式,eg:alist=[x*x for x in range(10)]
18、生成器推導式
用( )括起來的生成器推導式,eg:atuple= (x*x for x in range(10)) 其結果為生成器對象,使用next(),或則__next__()遍歷!
19、yield語句
20、python3開頭需要指定編碼類型
# !/usr/bin/env python # -*- coding: utf-8 -*-21 全局變量,局部變量與nonlocal
- 全局變量即在整個程序中,任何地方都可以訪問。
- 局部變量,試著在函數內部聲明的變量,當函數運行結束時,局部變量就會被內存釋放。
- 局部變量是有層次的,如果出現函數的嵌套,內層函數想調用外層的變量是,是不能用global聲明的,因為外層的變量不叫全局變量。這時候如果想修改外層的變量,就得用到一個新的關鍵字:nonlocal
22 yield, 作用:(1)生成一個“生成器”對象,并不執行(2)采用next調用 ,才能執行(3)執行yield,作用相當于return,(4)程序停止,等待next調用,繼續執行
22 數字 字符串 元祖 修改全局變量時需要加global,列表和字典以及其他可變類對象則不需要。
23 列表推導式,【表達式 for 變量 in 序列或者迭代對象】,相當于一個循環,生成的是一個列表。
24 生成器推導式, (表達式 for 變量 in 序列或者迭代對象), 生成的是一個生成器對象,只能通過next()方式訪問。
二、 循環語句的區別
- 1 python沒有do while語句
- 2 python沒有三目運算符,用 語句:’ x if a==b else c’ 代替
三、字符串區別
待續
四、函數的區別
1 PYTHON不需要指定函數的類型
2 PYTHON函數采用return可以返回一個或者多個值,類似于MATLAB, return a1, a2
3 PYTHON函數不需要指定形參的類型,根據實際調用函數時傳遞的實參自動推斷
4 在Python中參數傳遞采用的是值傳遞,這個和C語言有點類似;對于不可變對象,如:普通變量,。函數內部對形參進行修改,不會影響到實參的值;對于可變對象,如列表,字典,集合,對形參的修改將會影響實參的值。
5 PYTHON函數有關鍵參數,即按照參數名字來傳值
6 PYTHON函數有可變長度參數,*parameter代表的是元組, **parameter代表的是字典
7 PYTHON具有lambda表達式,即用來聲明匿名函數
8 作用域的LEGB原則
- L(Local)局部作用域 - E(Enclosing function locale)外部嵌套函數作用域 - G(Global module)函數定義所在模塊作用域 - B(Buildin): python內置模塊的作用域9 eval()函數:把一個字符串當成一個表達式來執行, 返回表達式執行后的結果
10 exec()函數: 跟eval功能類似, 但是,不返回結果
11 高階函數(函數名稱就是一個變量): 把函數作為參數使用的函數,叫高階函數
# 函數名稱就是一個變量 def funA():print("In funA")funB = funA funB()12 系統高階函數-map: 原意就是映射,即把集合或者列表的元素,每一個元素都按照一定規則(通常是函數)進行操作,生成一個新的列表或者集合
# map舉例 # 有一個列表,想對列表里的每一個元素乘以10, 并得到新的列表l1 = [i for i in range(10)] print(l1) l2 = [] for i in l1:l2.append(i * 10)print(l2)# 利用map實現 def mulTen(n):return n*10l3 = map(mulTen, l1 ) # map類型是一個可迭代的結構,所以可以使用for遍歷 for i in l3:print(i)# 以下列表生成式得到的結果為空, why? l4 = [i for i in l3] print(l4)13 reduce函數: 原意是歸并,縮減,把一個可迭代對象最后歸并成一個結果,對于作為參數的函數要求: 必須由兩個參數,必須由返回結果, reduce([1,2,3,4,5]) = f( f(f(f(1,2),3), 4),5),reduce 需要導入functools包
from functools import reduce# 定義一個操作函數 # 加入操作函數只是相加 def myAdd(x,y):return x + y# 對于列表[1,2,3,4,5,6]執行myAdd的reduce操作 rst = reduce( myAdd, [1,2,3,4,5,6] ) print(rst)14 filter 函數 過濾函數: 對一組數據進行過濾,符合條件(通常是函數)的數據會生成一個新的列表并返回;跟map相比較:
- 相同:都對列表的每一個元素逐一進行操作 - 不同:- map會生成一個跟原來數據想對應的新隊列- filter不一定,只要符合條件的才會進入新的數據集合 # filter案例 # 對于一個列表,對其進行過濾,偶數組成一個新列表# 需要定義過濾函數 # 過濾函數要求有輸入,返回布爾值 def isEven(a):return a % 2 == 0l = [3,4,56,3,2,3,4556,67,4,4,3,23455,43]rst = filter(isEven, l) # 返回的filter內容是一個可迭代對象 print(type(rst)) print(rst)print([i for i in rst])15 閉包(closure)
- 當一個函數在內部定義函數,并且內部的函數應用外部函數的參數或者局部變量,
- 當內部函數被當做返回值的時候,相關參數和變量保存在返回的函數中,這種結果,叫閉包
- 上面定義的myF4是一個標準閉包結構
- 閉包關鍵特征:其變量為nonlocal類型
輸出結果:
9
9
9
出現的問題:
造成上述狀況的原因是,返回函數引用了變量i, i并非立即執行,而是等到三個函數都返回的時候才統一使用,此時i已經變成了3,最終調用的時候,都返回的是 3*3
16 裝飾器(Decrator)
- 在不改動函數代碼的基礎上無限制擴展函數功能的一種機制,本質上講,裝飾器是一個返回函數的高階函數
- 裝飾器的使用: 使用@語法, 即在每次要擴展到函數定義前使用@+函數名
- 裝飾器的好處是,一點定義,則可以裝飾任意函數
- 一旦被其裝飾,則則把裝飾器的功能直接添加到定義函數的功能上
上面定義了裝飾器,使用的時候需要用到@, 此符號是python的語法糖
# 上面定義了裝飾器,使用的時候需要用到@, 此符號是python的語法糖 @printTime def hello():print("Hello world")hello()輸出:
Time: Mon Apr 2 21:14:52 2018
Hello world
17 偏函數
- 參數固定的函數,相當于一個由特定參數的函數體
- functools.partial的作用是,把一個函數某些函數固定,返回一個新函數
18 zip
- 把兩個可迭代內容生成一個可迭代的tuple元素類型組成的內容
輸出:
<class ‘zip’>
<zip object at 0x7f61c457ab88>
(1, 11)
(2, 22)
(3, 33)
(4, 44)
(5, 55)
19 enumerate
- 跟zip功能比較像
- 對可迭代對象里的每一元素,配上一個“索引”
- 然后索引和內容構成tuple類型 # enumerate案例1
l1 = [11,22,33,44,55]em = enumerate(l1)l2 = [i for i in em]
print(l2)
輸出:
[(0, 11), (1, 22), (2, 33), (3, 44), (4, 55)]
五 對象的區別
0 python中類變量和成員變量、局部變量總結
class Member():num=0 #類變量,可以直接用類調用,或用實例對象調用def __init__(self,x,y):self.x=x #實例變量(成員變量),需要它是在類的構造函數內以self.開頭來定義的self.y=yself.fuc(self.x,self.y)def add(self):total=2 #局部變量self.vara=3 # 局部變量,雖是以self.給出,但并沒有在構造函數中進行初始化self.varb=4fina=(self.x+self.y)*totalreturn finadef fuc(self,a,b):self.varc=a #成員變量,他們在成員函數fuc()中定義,但是在構造函數中調用了fuc()函數self.vard=b- (1) 可變變量作為類變量:對于列表、字典、自定義類這些可變變量,如果將其作為類變量,則是傳引用。即所有對象的類變量公用一個內存地址。
- (2)不可變變量作為類變量:對于INT,STRING這種不可變變量,如果將其作為類變量,則是傳值。即所有對象的類變量有各自的內存地址。
- (3)不管是可變變量還是不可變變量,只要是放在構造函數中,則都是傳值。即各個對象擁有自己的對象屬性。
1 PYTHON類的成員函數第一個參數固定為self
2 PYTHON構造函數為__init__()
3 _ init_()內定義和類方法內定義的變量為對象的數據成員
4 類內定義的變量為類的數據成員
5 可以動態的為類和對象增加成員
6 類的保護成員和保護函數前面用“_+成員名(函數名)"
7 類的私有成員和私有函數前面用”__+成員名(函數名)"
8 類的方法有:公有方法,私有方法,靜態方法,類方法
9 PYTHON 屬性, 可設置為只讀;可修改;可刪除(針對可動態的為類和對象增加成員)
- 屬性結合了公開數據成員和成員方法的優點,既可以像成員方法那樣對值進行必要的檢查(類似于C++的私有,公開,保護),又可以像數據成員一樣靈活的訪問。
10 數字 字符串 元祖 修改全局變量時需要加global,列表和字典以及其他可變類對象則不需要。
11 訪問基類可以通過:“super(繼承類名, self).方法名( ) ”或者“基類名.方法名( )”的方式
- super不是關鍵字, 而是一個類
- super的作用是獲取MRO(MethodResolustionOrder)列表中的第一個類
- super于父類直接沒任何實質性關系,但通過super可以調用到父類
- super使用兩個方,參見在構造函數中調用父類的構造函數
12 多態就是同一個對象在不同情況下有不同的狀態出現,Mixin設計模式
-
Mixin設計模式
- 主要采用多繼承方式對類的功能進行擴展
- Mixin概念
- MRO and Mixin
- Mixin模式
- Mixin MRO
- MRO
-
我們使用多繼承語法來實現Minxin
-
使用Mixin實現多繼承的時候非常小心
- 首先他必須表示某一單一功能,而不是某個物品
- 職責必須單一,如果由多個功能,則寫多個Mixin
- Mixin不能依賴于子類的實現
- 子類即使沒有繼承這個Mixin類, 也能照樣工作,只是缺少了某個功能
-
優點
- 使用Mixin可以在不對類進行任何修改的情況下,擴充功能
- 可以方便的組織和維護不同功能組件的劃分
- 可以根據需要任意調整功能類的組合
- 可以避免創建很多新的類,導致類的繼承混亂
-
13 類的成員描述符是為了在類中對類的成員屬性進行相關操作而創建的一種方式
- get: 獲取屬性的操作
- set:修改或者添加屬性操作
- delete: 刪除屬性的操作
- 如果想使用類的成員描述符,大概有三種方法
- 使用類實現描述器
- 使用屬性修飾符
- 使用property函數
- property函數很簡單
- property(fget, fset, fdel, doc)
- 案例參看notebook
- 如果想使用類的成員描述符,大概有三種方法
14 類的內置屬性
- __ dict__:以字典的方式顯示類的成員組成
- __ doc__: 獲取類的文檔信息
- __ name__:獲取類的名稱,如果在模塊中使用,獲取模塊的名稱
- __ bases__: 獲取某個類的所有父類,以元組的方式顯示
15 類的常用魔術方法
-
魔術方法就是不需要人為調用的方法,基本是在特定的時刻自動觸發
-
魔術方法的統一的特征: 方法名被前后各兩個下滑線包裹
-
操作類
- __ init__ : 構造函數
- __ str__: 當對象被當做字符串使用的時候調用
- __ repr__: 返回字符串,跟__str__具體區別請百度
- 描述符相關
__ set__
__ get__
__ delete__ - 屬性操作相關
__ getattr__: 訪問一個不存在的屬性時觸發
- __ setattr__: 對成員屬性進行設置的時候觸發
16 類和對象的三種方法
- 實例方法
- 需要實例化對象才能使用的方法,使用過程中可能需要截止對象的其他對象的方法完成
- 靜態方法
- 不需要實例化,通過類直接訪問
- 類方法
- 不需要實例化
17 抽象類
-
抽象方法: 沒有具體實現內容的方法成為抽象方法
-
抽象方法的主要意義是規范了子類的行為和接口
-
抽象類的使用需要借助abc模塊
- 抽象類:包含抽象方法的類叫抽象類,通常稱為ABC類
18. 結構體
有時候我們可能需要像C中的struct那樣的數據類型,把少量的數據項放在一起。Python中可以使用定義一個空類來實現這一點:
# filename:p.py class Employee:passjohn = Employee() # Create an empty employee record填充數據:
# Fill the fields of the record john.name = 'John Doe' john.dept = 'computer lab' john.salary = 1000 >>> import p >>> p.john <p.Employee instance at 0xb71f50ac> >>> p.john.name 'John Doe' >>> p.john.dept 'computer lab' >>> p.john.salary 1000六、文件操作
- 長久保存信息的一種數據信息集合
- 常用操作
- 打開關閉(文件一旦打開,需要關閉操作)
- 讀寫內容
- 查找
1 open函數
-
open函數負責打開文件,帶有很多參數
-
第一個參數: 必須有,文件的路徑和名稱
-
mode:表明文件用什么方式打開
- r:以只讀方式打開
- w:寫方式打開,會覆蓋以前的內容
- x:創建方式打開,如文件已經存在,報錯
- a:append方式,以追加的方式對文件內容進行寫入
- b: binary方式,二進制方式寫入
- t: 文本方式打開
- +: 可讀寫
-
open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
- 注意:中文必須加上: encoding='UTF-8’
注意:此案例說明,以寫方式打開文件,默認是如果沒有文件,則創建
2 with語句
- with語句使用的技術是一種成為上下文管理協議的技術(ContextManagementProtocal)
- 自動判斷文件的 作用域, 自動關閉不在使用的打開的文件句柄
建議用with語句 - r"test01.txt"中的r表示原義
2.1 readline函數用來一行一行的讀取文件
# with案例with open(r'test01.txt', 'r', encoding = 'UTF-8') as f:# 按行讀取內容strline = f.readline()# 此結構保證能夠完整讀取文件知道結束while strline:print(strline)strline = f.readline()輸出:
假若他日相逢
我將何以賀你
以沉默
以眼淚
2.2 list用打開的文件作為參數,把文件內每一行內容作為一個元素
# list能用打開的文件作為參數,把文件內每一行內容作為一個元素with open(r'test01.txt', 'r', encoding = 'UTF-8') as f:# 以打開的文件f作為參數,創建列表l = list(f)for line in l:print(line)輸出:
假若他日相逢
我將何以賀你
以沉默
以眼淚
2.3 read是按字符讀取文件內容
- read( )表示從文件頭讀到文件尾
- read(n)表示讀n個字符,一個漢字包含3個字節
- read 可以與tell以及seek函數聯合,獲取任意地址的文件內容
輸出:
1
假
3 seek(offset, from)
- 移動文件的讀取位置,也叫讀取指針
- from的取值范圍:
- 0: 從文件頭開始偏移
- 1:從文件當前位置開始偏移
- 2: 從文件末尾開始偏移
- 移動的單位是字節(byte)
- 一個漢字由若干個字節構成
- 返回文件只針對 當前位置
輸出:
他日相逢
我將何以賀你
以沉默
以眼淚
4 UTF-8中的中文字符占用3個字節
- 查看每個字符的二進制輸出
輸出:
<class ‘str’>
1
0b11101111
0b10111011
0b10111111
<class ‘str’>
1
0b1010
<class ‘str’>
1
0b11100101
0b10000001
0b10000111
4.1 tell函數: 用來顯示文件讀寫指針的當前位置
- 用法:pos = f.tell( )
輸出:
9
假若他
18
日相逢
25
我將
34
何以賀
41
你
以
48
沉默
57
以眼淚
5 文件的寫操作-write
- write(str): 把字符串寫入文件
- writeline(str): 把字符串按行寫入文件
- 區別:
- write函數參數只能是字符串
- writerline參數可以是字符串,也可以是字符序列
6 持久化 - pickle
- 序列化(持久化,落地):把程序運行中的信息保存在磁盤上
- 反序列化: 序列號的逆過程
- pickle: python提供的序列化模塊
- pickle.dump:序列化
- pickle.load:反序列化
輸出:
19
輸出:
[19, ‘liudana’, ‘i love wangxiaojing’, [185, 76]]
7 持久化-shelve
- 持久化工具
- 類似字典,用kv對保存數據,存取方式跟字典也類似
- open, close
- shelve打開了必須關閉
- 最好采用:**try…finally… **語句
輸出:
1
煩死了
8 json特性
- JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。
- JSON的數據格式其實就是python里面的字典格式,里面可以包含方括號括起來的數組,也就是python里面的列表。
- Json 模塊提供了四個方法: dumps、dump、loads、load
輸出:
<class ‘str’>
[1, 2, 3]
8.1 json的 dumps 和 dump:
- dumps和dump 序列化方法
- dumps只完成了序列化為str,
- dump必須傳文件描述符,將序列化的str保存到文件中
實例:
>>> import json >>> json.dumps([]) # dumps可以格式化所有的基本數據類型為字符串 '[]' >>> json.dumps(1) # 數字 '1' >>> json.dumps('1') # 字符串 '"1"' >>> dict = {"name":"Tom", "age":23} >>> json.dumps(dict) # 字典 '{"name": "Tom", "age": 23}' a = {"name":"Tom", "age":23} with open("test.json", "w", encoding='utf-8') as f:# indent 超級好用,格式化保存字典,默認為None,小于0為零個空格f.write(json.dumps(a, indent=4))# json.dump(a,f,indent=4) # 和上面的效果一樣8.2 json的loads 和 load
- loads和load 反序列化方法
- loads 只完成了反序列化,
- load 只接收文件描述符,完成了讀取文件和反序列化
實例:
>>> json.loads('{"name":"Tom", "age":23}') {'age': 23, 'name': 'Tom'} import json with open("test.json", "r", encoding='utf-8') as f:aa = json.loads(f.read())f.seek(0)bb = json.load(f) # 與 json.loads(f.read()) print(aa) print(bb)輸出:
{‘name’: ‘Tom’, ‘age’: 23}
{‘name’: ‘Tom’, ‘age’: 23}
總結
-
json序列化方法:
dumps:無文件操作 dump:序列化+寫入文件
-
json反序列化方法:
loads:無文件操作 load: 讀文件+反序列化
修改自圖靈學院課程文件
9 CSV文件讀寫
csv(comma separeated values) 格式的文件常用于電子表格和數據庫中的導入和導出。
- csv.reader(fp,delimiter= ’ ‘,quotechar=’ ')
- csv.writer(fp,delimiter=’ ‘, quotechar=’ ')
– writerrow( ) - csv.DictReader(fp)
- csv.DictWriter(fp,fieldnames=’ ')
七 異常處理
待續
八 多線程與進程
待續
總結
以上是生活随笔為你收集整理的C/C++与Python的语法差异的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 复合文档格式(五) - 短流、短流容器流
- 下一篇: c/c++笔试面试题_2