Python基礎(下)
前言
1 print("\n".join([''.join(['*'*((x-y)%3) if((x*0.05)**2+(y*0.1)**2 -1)**3-(x*0.05)**2*(y*0.1)**3<=0 else ' ' for x in range(-30,30)]) for y in range(15,-15,-1)]))
函式基礎(function)
1.定義函式
定義函式需要用到def關鍵詞,格式如下:
1 def 函式名(): 2 此函式做的事情1 3 此函式做的事情3 4 此函式做的事情2 5 ...省略...
定義了函式後,相當於有了一個具有某功能的程式碼塊,想要呼叫函式,通過函式名()
1 def addition():#定義函式 2 a = 2 3 b = 3 4 c = a + b 5 print(c) 6 addition()#呼叫函式
2.函式註釋說明
若想給函式添加註釋說明,讓外部呼叫者知道函式的大體功能,可以通過如下格式進行函式文件說明的新增:
1 def addition():#定義函式 2 '兩個數字求和' 3 a = 2 4 b = 3 5 c = a + b 6 print(c) 7 addition()#呼叫函式
3.函式引數
定義帶有引數的函式的方式如下:
1 def addition(a,b):#定義帶入引數的函式 2 '兩個數字求和' 3 c = a + b 4 print(c) 5 addition(2,3)#呼叫帶入引數的函式
4.函式返回值
想要函式中把結果返回給呼叫者,需要在函式中使用return。示例如下:
1 def addition(a,b):#定義函式 2 '兩個數字求和' 3 c = a + b 4 return c 5 result = addition(2,3)#呼叫函式 6 print(result)
5.函式型別
定義函式時小括號內的引數,用來接收引數所用,稱為“形參”。
呼叫函式時小括號內的引數,用來傳遞給函式所用,稱為”實參“。
函式一共有4種類型:
1.無引數,無返回值。
2.有引數,無返回值。
3.無引數,有返回值。
4.有引數,有返回值。
函式高階
1.函式返回多個值
python允許函式有多個返回值,本質時利用了元組,示例如下:
1 def addition(a,b): 2 return a+1,b+1 3 result = addition(2,3) 4 print(result)
2.預設引數
呼叫函式時,預設引數的值如果沒有傳入,則被認為時預設值,我們給引數賦值預設值的方式如下示例所示:
1 def addition(a,b=3): 2 return a+1,b+1 3 result = addition(2) 4 print(result)
注意:預設引數一定要位於引數列表的最後面。
3.不定長引數
有時需要函式處理比當初宣告時更多的引數,這些引數叫做不定長引數,宣告時不會命名。實現不定長引數的方式有兩種,
1.使用*引數名的方式,本質是一個元組。
2.使用**引數名的方式,本質是一個字典。
使用*變數名方式的示例如下:
1 def addition(a,b,*arg): 2 print(a) 3 print(b) 4 print(arg) 5 addition(1,2,3,4,5,6)
使用**變數名方式的示例如下:
1 def addition(a,b,**kwargs): 2 print(a) 3 print(b) 4 print(kwargs) 5 addition(1,2,name='jonins',age='18')
一個複雜例子說明:
1 def addition(a,b,c=3,*args,**kwargs): 2 print(a) 3 print(b) 4 print(c) 5 print(args) 6 print(kwargs) 7 print('--------2個必填引數---------') 8 addition(1,2) 9 print('-------2個必填1個預設其它為不定長*args----------') 10 addition(1,2,3,4) 11 print('-------2個必填1個預設其它為不定長**kwargs----------') 12 addition(1,2,name = 'jonins',age = '18') 13 print('-------2個必填1個預設有不定長*args和**kwargs----------') 14 addition(1,2,3,4,5,6,name = 'jonins',age = '18')
變數先賦值普通引數,省卻引數,最後為不定長變數。引數的宣告順序也要遵循如下順序宣告。
傳遞多餘的引數,如果前面不帶變數名,統統傳值給*變數名以元組形式儲存。
傳遞多餘的引數,如果前面帶有變數名,統統傳值給**變數名以字典形式儲存。
拆包
我們先看一個示例:
1 def addition(a,b,*args,**kwargs): 2 print(a) 3 print(b) 4 print(args) 5 print(kwargs) 6 A = {1,2,3,4} 7 B = {"name":"jonins","age":18} 8 addition(1,2,A,B)
因為值的前面不存在變數名,所以統統放進了元組中,若想將元組變數和字典變數,直接替換不定長引數中的變數,則需要拆包(元組前加1個*,字典前加2個*):
1 def addition(a,b,*args,**kwargs): 2 print(a) 3 print(b) 4 print(args) 5 print(kwargs) 6 A = {1,2,3,4} 7 B = {"name":"jonins","age":18} 8 addition(1,2,*A,**B)
全域性變數&區域性變數
區域性變數,就時在函式內部定義的變數。不同函式,可以i當以相同名字的區域性變數,但是各用各的不會產生影響。區域性變數的作用是為了臨時儲存資料需要在函式中定義變數來進行儲存。
如果一個變數,既能在一個函式中使用,也能在其它的函式中使用,這樣的變數就是全域性變數。
示例如下:
1 a = 100 2 def test1(): 3 print('test1,%i' % a) 4 def test2(): 5 print('test2,%i' % a) 6 def test3(): 7 a = 200 8 print('test3,%i' % a) 9 def test4(): 10 global a 11 a = 200 12 print('test4,%i' % a) 13 test1() 14 test2() 15 test3() 16 print('未使用global時,全域性變數外部為:%i'%a) 17 test4() 18 print('使用global時,全域性變數外部為:%i'%a)
說明:
1.函式外邊定義的變數叫做全域性變數。
2.全域性變數能夠在所有函式中進行訪問
3.如果在函式中修改全域性變數,需要使用global進行宣告。
4.如果全域性變數的名字和區域性變數的名字相同,那麼使用的是區域性變數的值(若名稱相同情況出現,預設是定義一個區域性變數,global時是修改)。
引用
1.變數賦值本質
python中變數的賦值並非單純的將值複製過去一份儲存起來,而是將變數值的引用複製過去儲存一份。
python中變數賦值過程大致描述:
C或C++中變數賦值過程大致描述:
可以通過id()方法驗證,id() 函式用於獲取物件的記憶體地址,示例如下:
1 a=100 2 b=a 3 c=b 4 print(id(a)) 5 print(id(b)) 6 print(id(c))
2.可變型別&不可變型別
python值靠引用的傳遞,那麼一個變數的值改變了,同樣引用的其它變數的值是否會變呢?
1 A = ['1','2','3','4'] 2 B = A 3 A.append('5') 4 print(B) 5 a = 100 6 b = a 7 a = 200 8 print(b)
我們可以看到列表的變數的值隨其它同引用變數對值的修改而發生了變化,但數值型別的變數卻沒有發生變化,這是因為python中型別分為可變型別與不可變型別。
可變型別,值可以改變:
列表(list)、字典(dict)
不可變型別,值不可以改變:
數值型別(int、long、bool、float)、字串(str)、元組(tuple)
注意:本質上不可變數型別在原值發生變化時,重新開闢空間生成了一個值的儲存區域並引用了新的地址,驗證示例:
1 a = 100 2 b = a 3 print(id(a)) 4 print(id(b)) 5 a = 200 6 print('--修改值後--') 7 print(id(a)) 8 print(id(b))
類基礎(class)
python是面向物件的,而面向物件程式設計的2個非常重要的概念就是:類和物件(如果你以前沒有接觸過面向物件的程式語言,那你可能需要先了解一些面嚮物件語言的一些基本特徵,在這裡不做過多描述)。
物件是面向物件程式設計的核心,在使用物件的過程中,為了將具有共同特徵和行為的一組物件抽象定義,提出了一個新的概念:類。而類的具體”實現“就是:物件。
1.定義類&實現類
類的定義和物件的實現的基本語法格式如下:
1 class CSharpCoder(): #定義類、經典類方式定義 2 'C#程式設計師' #CSharpCoder類的描述資訊 3 pass 4 class PythonCoder(object): #定義類、新式類方式定義 5 'Python程式設計師' #PythonCoder類的描述資訊 6 pass 7 cp_cder = CSharpCoder() #實現CSharpCoder類的物件 8 py_cder = PythonCoder() #實現PythonCoder類的物件
說明:
1.python中定義類有兩種方式:新式類和經典類。
2.規範要求類的命名方式採用:大駝峰。
3.pass:空語句,是為了保持程式結構的完整性,不做任何事情,一般用做佔位語句。
4.類的註釋和函式的註釋作用及語法是一樣的。
2.定義屬性
類中定義屬性的示例如下:
1 class CSharpCoder(): 2 name = '' 3 cp_cder = CSharpCoder() 4 cp_cder.name = 'Jonins' 5 print(cp_cder.name)
3.定義方法
類中定義方法的示例如下:
1 class CSharpCoder(): 2 name = 'k' 3 def get_name(self): 4 print(self.name) 5 cp_cder = CSharpCoder() 6 cp_cder.name = 'Jonins' 7 cp_cder.get_name()
python編寫類的內建函式時,第一個引數都是self。
因為當類初始化時會得到例項,self就是用於代表初始化得到的例項。在python設計之初,完全可以考慮似於Javascript中的this或C#隱藏掉例項讓人無感知(除非需要用到this)。
但是python的哲學是“Explicit is better than implicit”因此python類中的方法需要一個self引數代表例項。
4.建構函式(init)
python中類的的建構函式需要用到:__init__,使用示例如下:
1 class CSharpCoder(): 2 name = 'k' 3 def __init__(self,name): 4 print('例項化物件中...') 5 self.age = 18 6 self.name = name 7 def get(self): 8 print(self.age) 9 print(self.name) 10 cp_cder = CSharpCoder('Jonins') 11 cp_cder.get()
說明:
1.__init__()方法,在例項化一個物件時預設被呼叫的初始化方法,不需要手動呼叫。2.__init__(self)中的self引數,不需要開發者傳遞,python直譯器會自動把當前的物件引用傳遞進去。3.建構函式即例項化物件的一個標準,當__init__()方法指定self引數以外的引數時,外部例項化物件時必須傳遞所需的引數,否則報錯。
5.解構函式(del)
解構函式,在釋放物件時使用,需要用到__del()__,示例如下:
1 class CSharpCoder(): 2 def __init__(self): 3 print('例項化物件中...') 4 def __del__(self): 5 print('釋放物件中...') 6 cp_cder = CSharpCoder() 7 del cp_cder #刪除物件
解構函式在物件被刪除時會自動呼叫。
6.類專有函式
__init__ :建構函式,在生成物件時呼叫__del__ :解構函式,釋放物件時使用__repr__ :列印,轉換__setitem__ :按照索引賦值__getitem__:按照索引獲取值__len__:獲得長度__cmp__:比較運算__call__:函式呼叫__add__:加運算__sub__:減運算__mul__:乘運算__div__:除運算__mod__:求餘運算__pow__:乘方
self&__xxx__
1.self(自身)
所謂的self,可以理解為”自己“,類似於C++中類裡面的this指標一樣理解,就是物件自身的意思。某個物件呼叫其方法時,python直譯器會把這個物件自身當作第一個引數傳遞給self,所以開發者只需要傳遞後面的引數即可。
2.__xxx__(魔法方法)
在python中,方法如果是:__xxx__()形式的(雙下劃線所包圍),就表示具有一些特殊的功能,統稱為“Magic Method”,即魔法方法。
這些特殊方法不需要直接呼叫,在特殊的情況下這些特殊方法會自動被python呼叫。下面是python魔法方法的整理列表(整理自網路):
魔法方法 | 含義 |
基本的魔法方法 | |
__new__(cls[, ...]) | 1. __new__ 是在一個物件例項化的時候所呼叫的第一個方法2. 它的第一個引數是這個類,其他的引數是用來直接傳遞給 __init__ 方法3. __new__ 決定是否要使用該 __init__ 方法,因為 __new__ 可以呼叫其他類的構造方法或者直接返回別的例項物件來作為本類的例項,如果 __new__ 沒有返回例項物件,則 __init__ 不會被呼叫4. __new__ 主要是用於繼承一個不可變的型別比如一個 tuple 或者 string |
__init__(self[, ...]) | 構造器,當一個例項被建立的時候呼叫的初始化方法 |
__del__(self) | 析構器,當一個例項被銷燬的時候呼叫的方法 |
__call__(self[, args...]) | 允許一個類的例項像函式一樣被呼叫:x(a, b) 呼叫 x.__call__(a, b) |
__len__(self) | 定義當被 len() 呼叫時的行為 |
__repr__(self) | 定義當被 repr() 呼叫時的行為 |
__str__(self) | 定義當被 str() 呼叫時的行為 |
__bytes__(self) | 定義當被 bytes() 呼叫時的行為 |
__hash__(self) | 定義當被 hash() 呼叫時的行為 |
__bool__(self) | 定義當被 bool() 呼叫時的行為,應該返回 True 或 False |
__format__(self, format_spec) | 定義當被 format() 呼叫時的行為 |
有關屬性 | |
__getattr__(self, name) | 定義當用戶試圖獲取一個不存在的屬性時的行為 |
__getattribute__(self, name) | 定義當該類的屬性被訪問時的行為 |
__setattr__(self, name, value) | 定義當一個屬性被設定時的行為 |
__delattr__(self, name) | 定義當一個屬性被刪除時的行為 |
__dir__(self) | 定義當 dir() 被呼叫時的行為 |
__get__(self, instance, owner) | 定義當描述符的值被取得時的行為 |
__set__(self, instance, value) | 定義當描述符的值被改變時的行為 |
__delete__(self, instance) | 定義當描述符的值被刪除時的行為 |
比較操作符 | |
__lt__(self, other) | 定義小於號的行為:x < y 呼叫 x.__lt__(y) |
__le__(self, other) | 定義小於等於號的行為:x <= y 呼叫 x.__le__(y) |
__eq__(self, other) | 定義等於號的行為:x == y 呼叫 x.__eq__(y) |
__ne__(self, other) | 定義不等號的行為:x != y 呼叫 x.__ne__(y) |
__gt__(self, other) | 定義大於號的行為:x > y 呼叫 x.__gt__(y) |
__ge__(self, other) | 定義大於等於號的行為:x >= y 呼叫 x.__ge__(y) |
算數運算子 | |
__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) | 定義按位或操作的行為:| |
反運算 | |
__radd__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rsub__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rmul__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rtruediv__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rfloordiv__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rmod__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rdivmod__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rpow__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rlshift__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rrshift__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__rxor__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
__ror__(self, other) | (與上方相同,當左運算元不支援相應的操作時被呼叫) |
增量賦值運算 | |
__iadd__(self, other) | 定義賦值加法的行為:+= |
__isub__(self, other) | 定義賦值減法的行為:-= |
__imul__(self, other) | 定義賦值乘法的行為:*= |
__itruediv__(self, other) | 定義賦值真除法的行為:/= |
__ifloordiv__(self, other) | 定義賦值整數除法的行為://= |
__imod__(self, other) | 定義賦值取模演算法的行為:%= |
__ipow__(self, other[, modulo]) | 定義賦值冪運算的行為:**= |
__ilshift__(self, other) | 定義賦值按位左移位的行為:<<= |
__irshift__(self, other) | 定義賦值按位右移位的行為:>>= |
__iand__(self, other) | 定義賦值按位與操作的行為:&= |
__ixor__(self, other) | 定義賦值按位異或操作的行為:^= |
__ior__(self, other) | 定義賦值按位或操作的行為:|= |
一元操作符 | |
__neg__(self) | 定義正號的行為:+x |
__pos__(self) | 定義負號的行為:-x |
__abs__(self) | 定義當被 abs() 呼叫時的行為 |
__invert__(self) | 定義按位求反的行為:~x |
型別轉換 | |
__complex__(self) | 定義當被 complex() 呼叫時的行為(需要返回恰當的值) |
__int__(self) | 定義當被 int() 呼叫時的行為(需要返回恰當的值) |
__float__(self) | 定義當被 float() 呼叫時的行為(需要返回恰當的值) |
__round__(self[, n]) | 定義當被 round() 呼叫時的行為(需要返回恰當的值) |
__index__(self) | 1. 當物件是被應用在切片表示式中時,實現整形強制轉換2. 如果你定義了一個可能在切片時用到的定製的數值型,你應該定義 __index__3. 如果 __index__ 被定義,則 __int__ 也需要被定義,且返回相同的值 |
上下文管理(with 語句) | |
__enter__(self) | 1. 定義當使用 with 語句時的初始化行為2. __enter__ 的返回值被 with 語句的目標或者 as 後的名字繫結 |
__exit__(self, exc_type, exc_value, traceback) | 1. 定義當一個程式碼塊被執行或者終止後上下文管理器應該做什麼2. 一般被用來處理異常,清除工作或者做一些程式碼塊執行完畢之後的日常工作 |
容器型別 | |
__len__(self) | 定義當被 len() 呼叫時的行為(返回容器中元素的個數) |
__getitem__(self, key) | 定義獲取容器中指定元素的行為,相當於 self[key] |
__setitem__(self, key, value) | 定義設定容器中指定元素的行為,相當於 self[key] = value |
__delitem__(self, key) | 定義刪除容器中指定元素的行為,相當於 del self[key] |
__iter__(self) | 定義當迭代容器中的元素的行為 |
__reversed__(self) | 定義當被 reversed() 呼叫時的行為 |
__contains__(self, item) | 定義當使用成員測試運算子(in 或 not in)時的行為 |
結語
關於繼承,重寫,靜態類,異常捕獲和處理、面向物件等其它內容因篇幅過長後續再補(到這裡儲備的基礎知識應該夠用了,後續若用到一些科學計算的庫在現學吧)。
接下來一段時間專注在演算法&資料結構,準備沉澱幾個月邁過這道坎。當中程式碼為加深瞭解儘可能寫兩套(C#和Python),感興趣的朋友可以關注。
謝謝大家。