阿里云天池Python训练营-打卡Task3
函數(shù)
函數(shù)的定義
- 函數(shù)以def關鍵詞開頭,后接函數(shù)名和圓括號()。
- 函數(shù)執(zhí)行的代碼以冒號起始,并且縮進。
- return [表達式] 結(jié)束函數(shù),選擇性地返回一個值給調(diào)用方。不帶表達式的return相當于返回None。
def functionname (parameters):
? ? ? ?"函數(shù)文檔字符串"
? ? ? ? functionsuite
? ? ? ? return [expression]
函數(shù)參數(shù)
Python 的函數(shù)具有非常靈活多樣的參數(shù)形態(tài),既可以實現(xiàn)簡單的調(diào)用,又可以傳入非常復雜的參數(shù)。從簡到繁的參數(shù)形態(tài)如下:
- 位置參數(shù) (positional argument)
- 默認參數(shù) (default argument)
- 可變參數(shù) (variable argument)
- 關鍵字參數(shù) (keyword argument)
- 命名關鍵字參數(shù) (name keyword argument)
- 參數(shù)組合
參數(shù)組合
在 Python 中定義函數(shù),可以用位置參數(shù)、默認參數(shù)、可變參數(shù)、命名關鍵字參數(shù)和關鍵字參數(shù),這 5 種參數(shù)中的 4 個都可以一起使用,但是注意,參數(shù)定義的順序必須是:
- 位置參數(shù)、默認參數(shù)、可變參數(shù)和關鍵字參數(shù)。
- 位置參數(shù)、默認參數(shù)、命名關鍵字參數(shù)和關鍵字參數(shù)。
要注意定義可變參數(shù)和關鍵字參數(shù)的語法:
- *args?是可變參數(shù),args?接收的是一個?tuple
- **kw?是關鍵字參數(shù),kw?接收的是一個?dict
命名關鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名,同時可以提供默認值。定義命名關鍵字參數(shù)不要忘了寫分隔符?*,否則定義的是位置參數(shù)。
警告:雖然可以組合多達 5 種參數(shù),但不要同時使用太多的組合,否則函數(shù)很難懂。
變量作用域
- Python 中,程序的變量并不是在哪個位置都可以訪問的,訪問權限決定于這個變量是在哪里賦值的。
- 定義在函數(shù)內(nèi)部的變量擁有局部作用域,該變量稱為局部變量。
- 定義在函數(shù)外部的變量擁有全局作用域,該變量稱為全局變量。
- 局部變量只能在其被聲明的函數(shù)內(nèi)部訪問,而全局變量可以在整個程序范圍內(nèi)訪問。
- 當內(nèi)部作用域想修改外部作用域的變量時,就要用到global和nonlocal關鍵字了。
閉包
- 是函數(shù)式編程的一個重要的語法結(jié)構(gòu),是一種特殊的內(nèi)嵌函數(shù)。
- 如果在一個內(nèi)部函數(shù)里對外層非全局作用域的變量進行引用,那么內(nèi)部函數(shù)就被認為是閉包。
- 通過閉包可以訪問外層非全局作用域的變量,這個作用域稱為?閉包作用域。
- 閉包的返回值通常是函數(shù)。
- 如果要修改閉包作用域中的變量則需要?nonlocal?關鍵字
遞歸
- 如果一個函數(shù)在內(nèi)部調(diào)用自身本身,這個函數(shù)就是遞歸函數(shù)。
Lambda 表達式
匿名函數(shù)的定義
在 Python 里有兩類函數(shù):
- 第一類:用?def?關鍵詞定義的正規(guī)函數(shù)
- 第二類:用?lambda?關鍵詞定義的匿名函數(shù)
Python 使用?lambda?關鍵詞來創(chuàng)建匿名函數(shù),而非def關鍵詞,它沒有函數(shù)名,其語法結(jié)構(gòu)如下:
lambda argument_list: expression
- lambda?- 定義匿名函數(shù)的關鍵詞。
- argument_list?- 函數(shù)參數(shù),它們可以是位置參數(shù)、默認參數(shù)、關鍵字參數(shù),和正規(guī)函數(shù)里的參數(shù)類型一樣。
- :- 冒號,在函數(shù)參數(shù)和表達式中間要加個冒號。
- expression?- 只是一個表達式,輸入函數(shù)參數(shù),輸出一些值。
注意:
- expression?中沒有 return 語句,因為 lambda 不需要它來返回,表達式本身結(jié)果就是返回值。
- 匿名函數(shù)擁有自己的命名空間,且不能訪問自己參數(shù)列表之外或全局命名空間里的參數(shù)。
匿名函數(shù)的應用
函數(shù)式編程 是指代碼中每一塊都是不可變的,都由純函數(shù)的形式組成。這里的純函數(shù),是指函數(shù)本身相互獨立、互不影響,對于相同的輸入,總會有相同的輸出,沒有任何副作用。
匿名函數(shù) 常常應用于函數(shù)式編程的高階函數(shù) (high-order function)中,主要有兩種形式:
- 參數(shù)是函數(shù) (filter, map)
- 返回值是函數(shù) (closure)
如,在?filter和map函數(shù)中的應用:
- filter(function, iterable)?過濾序列,過濾掉不符合條件的元素,返回一個迭代器對象,如果要轉(zhuǎn)換為列表,可以使用?list()?來轉(zhuǎn)換。
- map(function, *iterables)?根據(jù)提供的函數(shù)對指定序列做映射。
除了 Python 這些內(nèi)置函數(shù),我們也可以自己定義高階函數(shù)。
類與對象
對象 = 屬性 + 方法
對象是類的實例。換句話說,類主要定義對象的結(jié)構(gòu),然后我們以類為模板創(chuàng)建對象。類不但包含方法定義,而且還包含所有實例共享的數(shù)據(jù)。
- 封裝:信息隱蔽技術
我們可以使用關鍵字?class?定義 Python 類,關鍵字后面緊跟類的名稱、分號和類的實現(xiàn)。
- 繼承:子類自動共享父類之間數(shù)據(jù)和方法的機制
- 多態(tài):不同對象對同一方法響應不同的行動
self 是什么?
Python 的?self?相當于 C++ 的?this?指針。
類的方法與普通的函數(shù)只有一個特別的區(qū)別 —— 它們必須有一個額外的第一個參數(shù)名稱(對應于該實例,即該對象本身),按照慣例它的名稱是?self。在調(diào)用方法時,我們無需明確提供與參數(shù)?self?相對應的參數(shù)。
Python 的魔法方法
據(jù)說,Python 的對象天生擁有一些神奇的方法,它們是面向?qū)ο蟮?Python 的一切...
它們是可以給你的類增加魔力的特殊方法...
如果你的對象實現(xiàn)了這些方法中的某一個,那么這個方法就會在特殊的情況下被 Python 所調(diào)用,而這一切都是自動發(fā)生的...
類有一個名為__init__(self[, param1, param2...])的魔法方法,該方法在類實例化時會自動調(diào)用。
公有和私有
在 Python 中定義私有變量只需要在變量名或函數(shù)名前加上“__”兩個下劃線,那么這個函數(shù)或變量就會為私有的了。
繼承
Python 同樣支持類的繼承,派生類的定義如下所示:
class DerivedClassName(BaseClassName):
? ? ? ?statement-1
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?statement-N
BaseClassName(基類名)必須與派生類定義在一個作用域內(nèi)。除了類,還可以用表達式,基類定義在另一個模塊中時這一點非常有用:
class DerivedClassName(modname.BaseClassName):
? ? ? ?statement-1
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?statement-N
如果子類中定義與父類同名的方法或?qū)傩?#xff0c;則會自動覆蓋父類對應的方法或?qū)傩浴?/p>
解決該問題可用以下兩種方式:
- 調(diào)用未綁定的父類方法Fish.__init__(self)
- 使用super函數(shù)super().__init__()
Python 雖然支持多繼承的形式,但我們一般不使用多繼承,因為容易引起混亂。
class DerivedClassName(Base1, Base2, Base3):
? ? ? ?statement-1
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?? ? ? ?.
? ? ? ?statement-N
需要注意圓括號中父類的順序,若是父類中有相同的方法名,而在子類使用時未指定,Python 從左至右搜索,即方法在子類中未找到時,從左到右查找父類中是否包含方法。
類、類對象和實例對象
類對象:創(chuàng)建一個類,其實也是一個對象也在內(nèi)存開辟了一塊空間,稱為類對象,類對象只有一個。
class A(object):
? ? ? ?pass
實例對象:就是通過實例化類創(chuàng)建的對象,稱為實例對象,實例對象可以有多個。
類屬性:類里面方法外面定義的變量稱為類屬性。類屬性所屬于類對象并且多個實例對象之間共享同一個類屬性,說白了就是類屬性所有的通過該類實例化的對象都能共享。
實例屬性:實例屬性和具體的某個實例對象有關系,并且一個實例對象和另外一個實例對象是不共享屬性的,說白了實例屬性只能在自己的對象里面使用,其他的對象不能直接使用,因為self是誰調(diào)用,它的值就屬于該對象。
注意:屬性與方法名相同,屬性會覆蓋方法。
什么是綁定?
Python 嚴格要求方法需要有實例才能被調(diào)用,這種限制其實就是 Python 所謂的綁定概念。
Python 對象的數(shù)據(jù)屬性通常存儲在名為.__ dict__的字典中,我們可以直接訪問__dict__,或利用 Python 的內(nèi)置函數(shù)vars()獲取.__ dict__。
一些相關的內(nèi)置函數(shù)(BIF)
- issubclass(class, classinfo)?方法用于判斷參數(shù) class 是否是類型參數(shù) classinfo 的子類。
- 一個類被認為是其自身的子類。
- classinfo可以是類對象的元組,只要class是其中任何一個候選類的子類,則返回True。
- isinstance(object, classinfo)?方法用于判斷一個對象是否是一個已知的類型,類似type()。
- type()不會認為子類是一種父類類型,不考慮繼承關系。
- isinstance()會認為子類是一種父類類型,考慮繼承關系。
- 如果第一個參數(shù)不是對象,則永遠返回False。
- 如果第二個參數(shù)不是類或者由類對象組成的元組,會拋出一個TypeError異常。
- hasattr(object, name)用于判斷對象是否包含對應的屬性。
- getattr(object, name[, default])用于返回一個對象屬性值。
- setattr(object, name, value)對應函數(shù)?getattr(),用于設置屬性值,該屬性不一定是存在的。
- delattr(object, name)用于刪除屬性。
- class property([fget[, fset[, fdel[, doc]]]])用于在新式類中返回屬性值。
- fget?-- 獲取屬性值的函數(shù)
- fset?-- 設置屬性值的函數(shù)
- fdel?-- 刪除屬性值函數(shù)
- doc?-- 屬性描述信息
魔法方法
魔法方法總是被雙下劃線包圍,例如__init__。
魔法方法是面向?qū)ο蟮?Python 的一切。
魔法方法的“魔力”體現(xiàn)在它們總能夠在適當?shù)臅r候被自動調(diào)用。
魔法方法的第一個參數(shù)應為cls(類方法) 或者self(實例方法)。
- cls:代表一個類的名稱
- self:代表一個實例對象的名稱
基本的魔法方法
- __init__(self[, ...])?構(gòu)造器,當一個實例被創(chuàng)建的時候調(diào)用的初始化方法
- __new__(cls[, ...])?在一個對象實例化的時候所調(diào)用的第一個方法,在調(diào)用__init__初始化前,先調(diào)用__new__。
- __new__至少要有一個參數(shù)cls,代表要實例化的類,此參數(shù)在實例化時由 Python 解釋器自動提供,后面的參數(shù)直接傳遞給__init__。
- __new__對當前類進行了實例化,并將實例返回,傳給__init__的self。但是,執(zhí)行了__new__,并不一定會進入__init__,只有__new__返回了,當前類cls的實例,當前類的__init__才會進入。
- 若__new__沒有正確返回當前類cls的實例,那__init__是不會被調(diào)用的,即使是父類的實例也不行,將沒有__init__被調(diào)用。
- __new__方法主要是當你繼承一些不可變的 class 時(比如int, str, tuple), 提供給你一個自定義這些類的實例化過程的途徑。
- __del__(self)?析構(gòu)器,當一個對象將要被系統(tǒng)回收之時調(diào)用的方法。
-
Python 采用自動引用計數(shù)(ARC)方式來回收對象所占用的空間,當程序中有一個變量引用該 Python 對象時,Python 會自動保證該對象引用計數(shù)為 1;當程序中有兩個變量引用該 Python 對象時,Python 會自動保證該對象引用計數(shù)為 2,依此類推,如果一個對象的引用計數(shù)變成了 0,則說明程序中不再有變量引用該對象,表明程序不再需要該對象,因此 Python 就會回收該對象。
大部分時候,Python 的 ARC 都能準確、高效地回收系統(tǒng)中的每個對象。但如果系統(tǒng)中出現(xiàn)循環(huán)引用的情況,比如對象 a 持有一個實例變量引用對象 b,而對象 b 又持有一個實例變量引用對象 a,此時兩個對象的引用計數(shù)都是 1,而實際上程序已經(jīng)不再有變量引用它們,系統(tǒng)應該回收它們,此時 Python 的垃圾回收器就可能沒那么快,要等專門的循環(huán)垃圾回收器(Cyclic Garbage Collector)來檢測并回收這種引用循環(huán)。
-
__str__(self):
- 當你打印一個對象的時候,觸發(fā)__str__
- 當你使用%s格式化的時候,觸發(fā)__str__
- str強轉(zhuǎn)數(shù)據(jù)類型的時候,觸發(fā)__str__
-
__repr__(self):
- repr是str的備胎
- 有__str__的時候執(zhí)行__str__,沒有實現(xiàn)__str__的時候,執(zhí)行__repr__
- repr(obj)內(nèi)置函數(shù)對應的結(jié)果是__repr__的返回值
- 當你使用%r格式化的時候 觸發(fā)__repr__
__str__(self)?的返回結(jié)果可讀性強。也就是說,__str__?的意義是得到便于人們閱讀的信息,就像下面的 '2019-10-11' 一樣。
__repr__(self)?的返回結(jié)果應更準確。怎么說,__repr__?存在的目的在于調(diào)試,便于開發(fā)者使用。
算術運算符
類型工廠函數(shù),指的是“不通過類而是通過函數(shù)來創(chuàng)建對象”。
- __add__(self, other)定義加法的行為:+
- __sub__(self, other)定義減法的行為:-
- __mul__(self, other)定義乘法的行為:*
- __truediv__(self, other)定義真除法的行為:/
- __floordiv__(self, other)定義整數(shù)除法的行為://
- __mod__(self, other)?定義取模算法的行為:%
- __divmod__(self, other)定義當被?divmod()?調(diào)用時的行為
- divmod(a, b)把除數(shù)和余數(shù)運算結(jié)果結(jié)合起來,返回一個包含商和余數(shù)的元組(a // b, a % b)。
- __pow__(self, other[, module])定義當被?power()?調(diào)用或?**?運算時的行為
- __lshift__(self, other)定義按位左移位的行為:<<
- __rshift__(self, other)定義按位右移位的行為:>>
- __and__(self, other)定義按位與操作的行為:&
- __xor__(self, other)定義按位異或操作的行為:^
- __or__(self, other)定義按位或操作的行為:|
反算術運算符
反運算魔方方法,與算術運算符保持一一對應,不同之處就是反運算的魔法方法多了一個“r”。當文件左操作不支持相應的操作時被調(diào)用。
- __radd__(self, other)定義加法的行為:+
- __rsub__(self, other)定義減法的行為:-
- __rmul__(self, other)定義乘法的行為:*
- __rtruediv__(self, other)定義真除法的行為:/
- __rfloordiv__(self, other)定義整數(shù)除法的行為://
- __rmod__(self, other)?定義取模算法的行為:%
- __rdivmod__(self, other)定義當被 divmod() 調(diào)用時的行為
- __rpow__(self, other[, module])定義當被 power() 調(diào)用或?**?運算時的行為
- __rlshift__(self, other)定義按位左移位的行為:<<
- __rrshift__(self, other)定義按位右移位的行為:>>
- __rand__(self, other)定義按位與操作的行為:&
- __rxor__(self, other)定義按位異或操作的行為:^
- __ror__(self, other)定義按位或操作的行為:|
增量賦值運算符
- __iadd__(self, other)定義賦值加法的行為:+=
- __isub__(self, other)定義賦值減法的行為:-=
- __imul__(self, other)定義賦值乘法的行為:*=
- __itruediv__(self, other)定義賦值真除法的行為:/=
- __ifloordiv__(self, other)定義賦值整數(shù)除法的行為://=
- __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()調(diào)用時的行為
- __invert__(self)定義按位求反的行為:~x
屬性訪問
- __getattr__(self, name): 定義當用戶試圖獲取一個不存在的屬性時的行為。
- __getattribute__(self, name):定義當該類的屬性被訪問時的行為(先調(diào)用該方法,查看是否存在該屬性,若不存在,接著去調(diào)用__getattr__)。
- __setattr__(self, name, value):定義當一個屬性被設置時的行為。
- __delattr__(self, name):定義當一個屬性被刪除時的行為。
描述符
描述符就是將某種特殊類型的類的實例指派給另一個類的屬性。
- __get__(self, instance, owner)用于訪問屬性,它返回屬性的值。
- __set__(self, instance, value)將在屬性分配操作中調(diào)用,不返回任何內(nèi)容。
- __del__(self, instance)控制刪除操作,不返回任何內(nèi)容。
定制序列
協(xié)議(Protocols)與其它編程語言中的接口很相似,它規(guī)定你哪些方法必須要定義。然而,在 Python 中的協(xié)議就顯得不那么正式。事實上,在 Python 中,協(xié)議更像是一種指南。
容器類型的協(xié)議
- 如果說你希望定制的容器是不可變的話,你只需要定義__len__()和__getitem__()方法。
- 如果你希望定制的容器是可變的話,除了__len__()和__getitem__()方法,你還需要定義__setitem__()和__delitem__()兩個方法。
- __len__(self)定義當被len()調(diào)用時的行為(返回容器中元素的個數(shù))。
- __getitem__(self, key)定義獲取容器中元素的行為,相當于self[key]。
- __setitem__(self, key, value)定義設置容器中指定元素的行為,相當于self[key] = value。
- __delitem__(self, key)定義刪除容器中指定元素的行為,相當于del self[key]。
迭代器
- 迭代是 Python 最強大的功能之一,是訪問集合元素的一種方式。
- 迭代器是一個可以記住遍歷的位置的對象。
- 迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。
- 迭代器只能往前不會后退。
- 字符串,列表或元組對象都可用于創(chuàng)建迭代器。
- 迭代器有兩個基本的方法:iter()?和?next()。
- iter(object)?函數(shù)用來生成迭代器。
- next(iterator[, default])?返回迭代器的下一個項目。
- iterator?-- 可迭代對象
- default?-- 可選,用于設置在沒有下一個元素時返回該默認值,如果不設置,又沒有下一個元素則會觸發(fā)?StopIteration?異常。
把一個類作為一個迭代器使用需要在類中實現(xiàn)兩個魔法方法?__iter__()?與?__next__()?。
- __iter__(self)定義當?shù)萜髦械脑氐男袨?#xff0c;返回一個特殊的迭代器對象, 這個迭代器對象實現(xiàn)了?__next__()?方法并通過?StopIteration?異常標識迭代的完成。
- __next__()?返回下一個迭代器對象。
- StopIteration?異常用于標識迭代的完成,防止出現(xiàn)無限循環(huán)的情況,在?__next__()?方法中我們可以設置在完成指定循環(huán)次數(shù)后觸發(fā)?StopIteration?異常來結(jié)束迭代。
生成器
- 在 Python 中,使用了?yield?的函數(shù)被稱為生成器(generator)。
- 跟普通函數(shù)不同的是,生成器是一個返回迭代器的函數(shù),只能用于迭代操作,更簡單點理解生成器就是一個迭代器。
- 在調(diào)用生成器運行的過程中,每次遇到?yield?時函數(shù)會暫停并保存當前所有的運行信息,返回?yield?的值, 并在下一次執(zhí)行?next()?方法時從當前位置繼續(xù)運行。
- 調(diào)用一個生成器函數(shù),返回的是一個迭代器對象。
總結(jié)
以上是生活随笔為你收集整理的阿里云天池Python训练营-打卡Task3的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 建议64:为循环增加Tester-Doe
- 下一篇: 什么是TXT记录?如何设置、检测TXT记