摘要:測試對象是否為某類型返回以內的倍數返回是一堆或者當為偶數時生成一個新列表將其加入中的,就是用定義的一個匿名函數,并通過函數,將其應用到列表中的每個元素。
1.1 使用函數
在Python中,函數必須先聲明,然后才能調用它,使用函數時,只要按照函數定義的形式,向函數傳遞必需的參數,就可以調用函數完成相應的功能或者獲得函數返回的處理結果。
如果函數有返回值,那么需要在函數中使用return語句返回計算結果,聲明函數的一般形式如下。
1.1.1 聲明函數并調用
def <函數名 > (參數列表):
<函數語句>
return <返回值>
其中參數列表和返回值不是必須的,return后也可以不跟返回值,甚至連return也沒有。對于return后沒有返回值的和沒有return語句的函數都會返回None值。
有些函數可能既不需要傳遞參數,也沒有返回值。
def tpl_sum( T ): result = 0 for i in T: result += i return result1.2深入函數 1.2.1默認值參數
聲明一個參數具有默認值的函數形式如下。
def <函數名> (參數=默認值):
<語句>
聲明了一個帶默認值參數的函數,代碼如下:
def hello (name="Python"): print ("你好,%s!" % name) print ("無參數調用時的輸出:") hello() print ("有參數("Jonson")調用時的輸出:") hello("Jonson")1.2.2參數傳遞
調用函數提供參數時,按順序傳遞的參數要位于關鍵字參數之前,而且不能有重復的情況。
1.2.3可變數量的參數傳遞在自定義函數時,如果參數名前加上一個星號“*”,則表示該參數就是一個可變長參數。在調用該函數時,如果依次序將所有的其他變量都賦予值之后,剩下的參數將會收集在一個元組中,元組的名稱就是前面帶星號的參數名。
def change_para_num (*tp1): print (type (tp1)) #輸出tp1變量的類型 print (tp1) change_para_num (1) change_para_num (1,2,3)
當自定義函數時,參數中含有前面所介紹的三種類型的參數,則一般來說帶星號的參數應放在最后。當帶星號的參數放在最前面時,仍然可以正常工作,但調用時后面的參數必須以關鍵字參數方式提供,否則因其后的位置參數無法獲取值而引發錯誤。
def change_para_num(*tpl,a,b=0,,**dict): print("tp1:",tp1) print("dict",dict) print("a:",a) print ("b:",b) change_para_num (1,2,3,a=5,c=1,d=2,e=3) #c d e 會以字典的形式儲存 change_para_num(1,2,3) #該調用會出錯,a變量沒有默認值,也不能獲取值
如果要收集不定數量的關鍵字參數可以在自定義函數時的參數前加兩顆星即**valuename,可以以字典的方式被收集到變量valuename之中。
def cube (name, **nature): all_nature = {"x":1, "y":1, "z":1, "color":"white", "weight":1} all_nature.update (nature) print (name,"立方體的屬性:") print ("體積:",all_nature ["x"]*all_nature ["y"]*all_nature ["z"]) print ("顏色:",all_nature ["color"]) print ("重量:",all_nature ["weight"]) cube ("first") #只給出必要參數的調用 cube ("second",y=3, color="red") #提供部分可選參數 cube ("third", z=2, color="green", weight=10) #提供部分可選參數1.2.4拆解序列的函數調用
前面使用函數調用時提供的參數都是位置參數和關鍵字參數,實際上調用函數時還可以把元組和字典進行拆解調用。
拆解元組提供位置參數;
拆解字典提供關鍵字參數。
調用時使用拆解元組的方法是在調用時提供的參數前加一個*號;要拆解字典必須在提供的調用參數前加兩個*號。
def mysum (a,b): return a+b print ("拆解元組調用:") print (mysum(* (3,4))) #調用時拆解元組作為位置參數 print ("拆解字典調用:") print (mysum(**{"a":3, "b":4}) #調用時拆解字典作為關鍵字參數1.2.5函數調用時參數的傳遞方法
Python中的元素有可變和不可變之分,如整數、浮點數、字符串、元組等都屬于不可變的;而列表和字典都屬于可變的。
列表和字典的可變也是很好理解的,即它們可以增減元素、修改元素的值。那么整數、浮點數、字符串等為什么是不可變的呢?
“=”號的作用是將對象引用與內存中某對象進行綁定,既然整數是不可變的,那么怎么改變一個指向整數的變量的值的呢?答案是直接在內存中創建一個新的整數值,然后將變量引用與其綁定,這雖然本質上的其他高級語言不同,但在使用上是看不出什么差別的,但若將其提供給函數作為參數,則效果不同。
在函數調用時,若提供的是不可變參數,那么在函數內部對其修改時,在函數外部其值是不變的;若提供是可變參數,則在函數內部對它修改時,在函數外部其值也會改變的。
def change (aint, alst): #定義函數 aint = 0 #修改 aint 值 alst[0]=0 #修改alst第1個值為0 alst.append (4) #在 alst 中添加一個元素4 print ("函數中aint:", aint) #輸出函數中的aint的值 print ("函數中alst:", alst) #輸出函數中的alst的值 aint = 3 alst = [1,2,3] print ("調用前aint:", aint) print ("調用前 alst:", alst) change(aint, alst) print ("調用后aint:", aint) #調用后值和調用前值相同 print ("調用后alst:", alst) #調用后值和調用前值不同
def myfun (lst= []): #定義有一個默認值為空列表的參數 lst.append("abc") print (lst) #此后三次調用自定義函數 myfun() myfun() myfun() #每次調用函數按默認值的理解,應該每次傳入空列表,列表中只有一個元素"abc" #在該函數的域上lst是已經存在的,在一個線程內多次執行會保留上一次執行的值。
def myfun (lst=None): #定義有一個默認值為空列表的參數 lst = [] if lst is None else lst lst.append("abc") print (lst) myfun() myfun() myfun() #增加一條推導語句,將lst置空,就可以達到想要的效果。1.3變量的作用域
內置作用域:Python預先定義的;
全局作用域:所編寫的整個程序;
局部作用域:某個函數內部范圍。
每次執行函數,都會創建一個新的命名空間,這個新的命名空間就是局部作用域,同一函數不同時間運行,其作用域是獨立的,不同的函數也可以具有相同的參數名,其作用域也是獨立的。
在函數內已經聲明的變量名,在函數以外依然可以使用。并且在程序運行的過程中,其值并不相互影響。
def myfun(): a = 0 #函數內聲明并初始化變量a為整數,局部作用域 a += 3 #修改a的值 print ("函數內a:", a) #輸出函數內a的值 a = "external" #全局作用域內a聲明并初始化 print ("全局作用域a:", a) myfun() #調用函數myfun() print("全局作用域a:", a) #總結:函數內部聲明的a和外部聲明的a在各自的域上互不干擾!
#那么如何在函數內使用全局作用域的變量呢? def myfun(): global a #增加此語句 a = 0 a += 3 print ("函數內a:", a) a = "external" print ("全局作用域a:",a) myfun() print ("全局作用域a:", a)
在局部作用域內可以引用全局作用域內的變量,但不可以修改它。
比如以下代碼是沒有錯誤的:
a = 3 #定義全局變量
def myprint(): #聲明函數myprint()
print (a) #引用全局變量
運行函數myprint()時,會輸出全局變量a的值3。但是若將其改為則會引發錯誤:
a = 3 #定義全局變量
def myprint(): #聲明函數myprint()
print (a) #引用全局變量
a = 5
以上代碼引發的錯誤是局部變量在分配前不能引用,原因是與Python中的變量查找有關,在此外代碼中函數內聲明了a變量并初始化,所以a被判為局部變量,但卻之前在print(a)中引用了它。
Python中的變量查找:
1.4使用匿名函數(lambda)語法形式如下: lambda params:expr
其中params相當于聲明函數時的參數列表中用逗號分隔的參數,expr是函數要返回值的表達式,而表達式中不能包含其他語句,也可以返回元組(要用括號),還允許在表達式中調用其他函數。
lambda的示例代碼:
import math s = lambda x1, y1, x2, y2:math. sqrt( (x1-x2) **2+(y1-y2) **2) s(1,1,0,0) #結果:1.4142135623730951
代碼的第二行定義了一個求兩坐標點距離的匿名函數,并用s引用,之后調用它來求(1,1)與(0,0)坐標點的距離,結果為1.414。
這里的params是參數列表。它的結構與Python中函數(function)的參數列表是一樣的。具體來說,argument_list可以有非常多的形式。例如:
a, b a=1, b=2 *args **kwargs a, b=1, *args
這里的expr是一個關于參數的表達式。表達式中出現的參數需要在argument_list中有定義,并且表達式只能是單行的。以下都是合法的表達式:
1 None a + b sum(a) 1 if a >10 else 0
下面是一些lambda函數示例:
lambda x, y: x*y;函數輸入是x和y,輸出是它們的積x*y lambda:None;函數沒有輸入參數,輸出是None lambda *args: sum(args); 輸入是任意個數的參數,輸出是它們的和(隱性要求是輸入參數必須能夠進行加法運算) lambda **kwargs: 1;輸入是任意鍵值對參數,輸出是1
簡單匿名函數 寫起來快速而簡單,省代碼;
不復用的函數 在有些時候需要一個抽象簡單的功能,又不想多帶帶定義一個函數;
為了代碼清晰 有些地方使用它,代碼更清晰易懂。
比如在某個函數中需要一個重復使用的表達式,就可以使用lambda來定義一個匿名函數,多次調用時,就可以少寫代碼,但條理清晰。
1.5Python常用內建函數沒有導入任何模塊或包時Python運行時提供的函數稱為內建函數
dir(obj) | 列出對象的相關信息 |
---|---|
help(obj) | 顯示對象的幫助信息 |
bin(aint) | 十進制數轉換為二進制數的字符串形式 |
hex(aint) | 十進制數轉換為十六進制數的字符串形式 |
oct(aint) | 十進制數轉換為八進制數的字符串形式 |
callable(obj) | 測試對象是否可調用(函數) |
chr(aint) | ascii碼轉為字符 |
ord(char) | 將字符轉為ascii碼 |
filter(seq) | 簡單的理解為過濾器,需要兩個參數,function,和一個序列(字符串、列表、元組都是序列),過濾器會依次將序列的值傳入function中,如果返回True的話,將其重新生成一個列表返回。 |
map(seq) | 和filter()類似,也是將序列放入函數進行運算,但是,不論運算結果為什么,map()都將忠實反饋,這是map()和filter()的主要區別。請注意,filter()和map()中的function都必要有一個返回值。 |
isinstance(obj,typestr) | 測試對象是否為某類型 |
print(list(filter(lambda x:True if x % 3 == 0 else False, range(100)))) #返回100以內3的倍數 print(list(map(lambda x:True if x % 3 == 0 else False, range(100))))#返回是一堆true或者false print(list(filter (lambda x:x % 2, alst)))#當x為偶數時生成一個新列表將其加入 print(list (map (lambda x:2*x,alst)))#list(map(lambda x:2*x,alst))中的lambda x:2*x,就是用lambda定義的一個匿名函數,并通過map()函數,將其應用到alst列表中的每個元素。1.6類的屬性和方法
class <類名>(父類名): pass class MyClass(): "pass" myclass=MyClass() help(MyClass) 輸出MyClass的幫助信息 print(myclass.__doc__) 輸出類的描述信息為pass1.6.1類的方法
類中的方法定義和調用與函數定義和調用的方式基本相同,其區別有:
方法的第一個參數必須是self,而且不能省略
方法的調用需要實例化類,并以實例名.方法名(參數列表)形式調用;
整體進行一個單位的縮進,表示其屬于類體中的內容。
class Demolnit:
def __init__(self,x,y=0): #定義構造方法,具有兩個初始化 self.x = x self.y = y def mycacl (self): #定義應用初始化數據的方法 return self.x + self.y def info (self): #定義一個類方法info() print ("我定義的類!") def mycacl_2 (self,x,y): #定義一個類方法mycacl() return x + y dia = Demolnit (3) #用一個參數實例化類 print ("調用mycacl方法的結果1:") print (dia.mycacl()) dib = Demolnit (3, 7) #用二個參數實例化類 print ("調用mycacl方法的結果2:") print (dib.mycacl())
def coord_chng(x,y): #定義一個全局函數,模擬坐標值變換 return (abs (x),abs (y)) #將x,y值求絕對值后返回 class Ant: #定義一個類Ant def __init__(self,x=0,y=0): #定義一個構造方法 self.x = x self.y = y self.disp_point() #構造函數中調用類中的方法disp_point() def move (self,x, y): #定義一個方法move() x,y = coord_chng(x,y) #調用全局函數,坐標變換 self.edit_point (x, y) #調用類中的方法edit_point() self.disp_point() #調用類中的方法disp_point() def edit_point (self, x,y): #定義一個方法 self.x += x self.y += y def disp_point (self): #定義一個方法 print ("當前位置:(%d,%d)" % (self .x, self.y)) ant_a = Ant() #實例化Ant()類 ant_a.move(2,4) #調用ant_a實例的方法move() ant_a.move (-9, 6) #調用ant_a實例的方法move()
類的屬性有兩類:
實例屬性;
類屬性。
實例屬性即同一個類的不同實例,其值是不相關聯的,也不會互相影響的,定義時使用“self.屬性名”,調用時也使用它;
類屬性則是同一個類的所有實例所共有的,直接在類體中獨立定義,引用時要使用“類名.類變量名”形式來引用,只要是某個實例對其進行修改,就會影響其他的所有這個類的實例。
class Demo_Property: #定義類 class_name = "Demo_Property" #類屬性 def __init__(self,x=0): self.x = x #實例屬性 def class_info (self): #輸出信息的方法 print ("類變量值:", Demo_Property.class_name) print ("實例變量值:", self.x) def chng (self,x): #修改實例屬性的方法 self.x = x #注意實例屬性的引用方式 def chng_cn (self, name): #修改類屬性的方法 Demo_Property.class_name = name #注意類屬性引用方式 dpa = Demo_Property() #實例化類 dpb = Demo_Property() #實例化類 print ("初始化兩個實例") dpa.class_info() dpb.class_info() print ("修改實例變量") print ("修改dpa實例變量") dpa.chng(3) dpa.class_info() dpb.class_info() print ("修改dpb實例變量") dpb.chng(10) dpa.class_info() dpb.class_info() #這里得到實例變量是屬于每個對象自己的。 print ("修改類變量") print ("修改dpa類變量") dpa.chng_cn("dpa") dpa.class_info() dpb.class_info() print ("修改dpb實例變量") dpb.chng_cn("dpb") dpa.class_info() dpb.class_info() #這里得到類變量是屬于每個對象共有的,一旦修改每個對象的類變量都會相應的改變。
綜上:對于實例屬性來說,兩個實例之間互不聯系,它們各自可以被修改為不同的值;對于類屬性來說,無論哪個實例修改了它,會導致所有實例的類屬性的值發生變化。
1.6.3 類成員方法與靜態方法類的屬性有類屬性和實例屬性之分,類的方法也有不同的種類,主要有:
實例方法;
類方法;
靜態方法。
前文中定義的所有類中的方法都是實例方法,其隱含調用參數是類的實例。類方法隱含調用參數則是類,靜態方法沒有隱含調用參數。類方法和靜態方法的定義方式都與實例方法不同,它們的調用方式也不同。
靜態方法定義時應使用裝飾器@staticmethod進行修飾,是沒有默認參數的。類方法定義時應使用裝飾器@classmethod進行修飾,必須有默認參數“cls”。它們的調用方式可以直接由類名進行調用,調用前也可以不實例化類,當然也可以用該類的任一個實例來進行調用。
class DemoMthd: #定義一個類 @staticmethod #靜態方法的裝飾器 def static_mthd(): #靜態類定義 print ("調用了靜態方法!") @classmethod #類方法的裝飾器 def class_mthd(cls): #類方法定義,帶默認參數cls print ("調用了類方法!") DemoMthd.static_mthd() #未實例化類,通過類名調用靜態方法 DemoMthd.class_mthd() #未實例化類,通過類名調用類方法 dm = DemoMthd() #實例化類 dm.static_mthd() #通過類實例調用靜態方法 dm.class_mthd() #通過類實例雅爾塔類方法1.7類的繼承
類是可以繼承的,并且也給出了繼承類的代碼格式。子類繼承了父類之后,就具有了父類的屬性與方法,但不能繼承父類的私有屬性和私有方法(屬性名或方法名前綴為兩個下畫線的__),子類中還可以重載來修改父類的方法,以實現與父類不同的行為表現或能力。
1.7.1 類的繼承演示了方法的重寫和添加
class Ant: #定義類Ant def __init__(self,x=0,y=0,color="black"):#定義構造方法 self.x = x self.y = y self.color =color def __crawl (self,x,y): #定義方法(模擬爬行) self.x = x self.y = y print ("爬行...") self.info() def info(self): print ("當前位置:(%d,%d)" % (self.x, self.y)) def attack (self): #定義方法(模擬攻擊) print ("用嘴咬!") class FlyAnt(Ant): #定義FlyAnt類,繼承Ant類 def attack (self): #修改行為(攻擊方法不同) print ("用尾針!") def fly(self,x,y): #定義方法(模擬飛行) print ("飛行...") self.x = x self.y = y self.info() flyant = FlyAnt (color="red") #實例化類 flyant.crawl(3,5) #__crawl此時會報錯無法繼承父類實例方法 #flyant.crawl(3,5) #調用方法(模擬爬行) flyant.fly(10,14) #調用訪求(模擬飛行) flyant.attack() #調用方法(模擬攻擊)1.7.2 多重繼承
在面向對象編程的語言中,有的允許多重繼承,即一個類可以繼承多個類;有的只允許單一繼承,即一個類只能繼承一個類,而Python中則允許多重繼承。
多重繼承的方式是在類定義時的繼承父類的括號中,以“,”分隔開要多重繼承的父類即可。而多重繼承時,繼承順序也是一個很重要的要素,如果繼承的多個父類中有相同的方法名,但在類中使用時未指定父類名,則Python解釋器將從左至右搜索,即調用先繼承的類中的同名方法。
1.7.3 方法的重載當子類繼承父類時,子類如果要想修改父類的行為,則應使用方法重載來實現,方法重載的基本方法是在子類中定義一個和所繼承的父類中需要重載方法同名的一個方法即可。
多重繼承中,兩個父類都具有同名方法info(),但在子類中也定義了一個info()方法,即info()方法被重載了。當子類實例調用info()方法時,就會直接調用該實例中定義的info()方法,而不會去調用任何一個父類的info()方法。
綜合來講一個同名方法先找子類,然后父類由先繼承到后繼承。
裝飾器重載:
import functools import locale from urllib import request # 函數重載 @functools.singledispatch def fun(arg, verbose=False): if verbose: print("Let me just say,", end=" ") print(arg) @fun.register(int) def _(arg, verbose=False): if verbose: print("Strength in numbers, eh?", end=" ") print(arg) @fun.register(list) def _(arg, verbose=False): if verbose: print("Enumerate this:") for i, elem in enumerate(arg): print(i, elem) print("函數重載") fun("test.", verbose=True) fun(42, verbose=True) fun(["spam", "spam", "eggs", "spam"], verbose=True) fun({"a":"txt","b":"dat"}, verbose=True)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42966.html
摘要:源碼年來都沒有動手跑一跑內置的函數。這一跑才發現平時自鳴得意的那些算法是有原生實現的,頓時有一種啪啪啪被打臉的感覺。希望亡羊補牢,為時不晚吧。下面是從里摘抄的歸納對比片段,希望對你有所啟發。 Demo源碼 3年來都沒有動手跑一跑PHP內置的Array函數。 這一跑才發現平時自鳴得意的那些算法是有原生實現的,頓時有一種啪啪啪被打臉的感覺。 希望亡羊補牢,為時不晚吧。 下面是從Demo里摘...
摘要:變量的函數引用的自定義屬性被稱為變量。為此,可讀性和可維護性是自定義屬性最大的優勢。自定義屬性作用域在中,變量有作用域一說。因此,在選擇器中聲明的自定義屬性,其作用域的范圍是全局范圍,也就是全局作用域。 引言 ??CSS語言是一種聲明式語言,不像其他語言有變量、條件和邏輯等特性,因為這個原因,社區中有了各種CSS處理器語言,比如Sass、LESS和Stylus等。這些處理器語言引入了一...
摘要:導語在開發中,會封裝一些自定義函數以及自定義的類,本篇文章講一下怎么使用實現自動加載。自定義函數實現自動加載,共有三步。自定義類自定義類同上,也是三步,一些小改動。參考資料自定義函數和自定義類。 導語 在開發中,會封裝一些自定義函數以及自定義的類,本篇文章講一下怎么使用 composer 實現自動加載。 自定義函數 實現自動加載,共有三步。 創建文件。在 app 目錄下創建 Help...
摘要:觸發事件可以攜帶數據,這些數據被用于傳遞給綁定了事件的其它組件的回調函數上,進而被傳遞給其它組件。父組件可以在回調函數里做任何事情,頗有靈活性。一般情況下,父組件會在回調函數中更新自己的狀態數據。 上一篇博文梳理了vue的數據驅動和響應式相關的特性,這一篇博文就來梳理vue的一個很重要的特性,組件化。自定義組件之于vue,其意義不亞于函數之于C,java之類的編程語言。函數是計算機科學...
摘要:但是到底是如何找到對應的函數的呢今天,我們來一起尋找答案函數分類首先,我們先回顧一下的函數分類,函數包含用戶自定義函數內部函數匿名函數等多種類型。用戶自定義函數和內部函數編譯完成后會將函數名注冊到全局函數列表中。 對于PHPer而言,我們通常會把常用的功能封裝成一個函數來進行復用,以提升開發效率。但是php到底是如何找到對應的函數的呢?今天,我們來一起尋找答案~ 函數分類 首先,我們先...
摘要:摘要本文對使用自定義域名觸發器搭建應用的步驟進行詳細介紹,手把手帶您三分鐘搭建穩定可靠的應用。函數計算搭建應用一觸發器中闡述了應用是函數計算很重要的一個使用場景。 摘要: 本文對使用自定義域名 + HTTP 觸發器搭建 Web 應用的步驟進行詳細介紹,手把手帶您三分鐘搭建穩定可靠的 Web 應用。 簡介阿里云 函數計算(Function Compute) 是事件驅動的全托管計算服務,是...
閱讀 1207·2019-08-30 15:55
閱讀 954·2019-08-30 15:55
閱讀 2150·2019-08-30 15:44
閱讀 2879·2019-08-29 14:17
閱讀 1130·2019-08-29 12:45
閱讀 3301·2019-08-26 10:48
閱讀 3133·2019-08-23 18:18
閱讀 2599·2019-08-23 16:47