python學習記錄(七)
0904--https://www.cnblogs.com/fnng/archive/2013/04/24/3039335.html
0904--https://www.cnblogs.com/fnng/archive/2013/04/26/3043856.html
將語句組織成函數
下面編寫一小段代碼計算婓波那契數列(前兩個數的和是第三個數)
因為賦完值fibs已經有兩個數了(0,1),所以循環8次之後,列表有10個數,兩個數相加等於第3個數。
由我們輸入來控制打印多少個數,num-2
fibs = [0,1] #定義一個列表,初始內容為0,1 num = int(input(‘How many fibonacci numbers do you want?‘)) for i in range(num-2): #循環num-2次 fibs.append(fibs[-1]+fibs[-2]) print(fibs) #輸入 How many fibonacci numbers do you want?14 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
創建函數
函數是可以調用的,它執行某種行為並且返回一個值。內建的callable函數可以用來判斷函數是否可調用:
>>> import math >>> x = 1 >>> y = math.sqrt>>> callable(x) False >>> callable(y) True
使用def語句定義函數
>>> def hello(name): return ‘hello.‘+name+‘!‘ #輸出 >>> print(hello(‘world‘)) hello.world!
將婓波那契數列定義成一個函數
def fibs(num): a = [0,1] for i in range(num): a.append(a[-1]+a[-2]) return a #調用fibs函數 >>> fibs(5) [0, 1, 1, 2, 3, 5, 8]
局部變量
當在函數內定義變量的時候,函數內定義的變量只在其函數內有效,與函數外具有相同名稱的其他變量沒有任何關系
#局部變量 def func(x): print (‘x is ‘,x) x = 2 print (‘changed local x to‘,x) x = 50 func(x) #func函數並沒有返回數據 print (‘x is still‘,x) #輸出 x is 50 changed local x to 2 x is still 50
global 語句
如果想把一個變量聲名為 全局的,則可以使用global語句。
#全局變量 def func(): global x print (‘x is‘,x) x = 2 print (‘changed local x to‘,x) x = 50 func() print (‘value of x is‘,x) #輸出 x is 50 changed local x to 2 value of x is 2
默認參數
對於一些參數,我們希望它的一些參數是可選的,如果用戶不想要為這些參數提供值的話,這些參數就使用默認值。
定義的say函數的第二個參數就是可選的,默認為times=1;也就是將兩個參數相乘輸出。
註意:只有在形參表末尾的那些參數可以有默認參數,如def func(a=5,b) 是無效的。
def say(message,times=1): print (message*times) say(‘hello‘) say(‘world‘,5) #輸出 hello worldworldworldworldworld
關鍵參數
如果某個函數有許多參數,而我們只想指定其中的一部分,那麽可以使用名字(關鍵字)而不是位置來給函數指定實參。----這被稱作 關鍵參數(這樣做,就不必擔心參數的順序,使用函數變得更加簡單。假設其它函數都有默認值,我們可以只給自己想要的參數賦值。)
def func(a,b=5,c=10): print (‘a is‘,a,‘and b is‘,b,‘and c is‘,c) func(3,7) func(24,c=32) func(c=32,a=14) #輸出 a is 3 and b is 7 and c is 10 a is 24 and b is 5 and c is 32 a is 14 and b is 5 and c is 32
遞歸:
有用的遞歸函數包含以下幾個部分:
- 當函數直接返回值時有基本實例(最小可能性問題)
- 遞歸實例,包括一個或者多個問題最小部分的遞歸調用。
def f(n): if n == 1: return 1 else: return n*f(n-1)
創建對象
面向對象概念:繼承、封裝、多態(具體區別,可以參考:https://www.cnblogs.com/qiuting/p/5347655.html)
- 多態:可對不同類的對象使用同樣的操作
- 封裝:對外部世界隱藏對象的工作細節
- 繼承:以普通的類為基礎建立專門的類對象
多態
多態的意思是“有多種形態”。多態意味著就算不知道變量所引用的對象類是什麽,還是能對它進行操作,而它也會根據對象(或類)類型的不同而表現出不同的行為。
從最簡單的開始
任何不知道對象到底是什麽類型,但是又要對對象“做點什麽”的時候,都會用到多態。這不僅限於方法--很多內建運算符和函數都有多態的性質,參考以下的例子:
>>> 1+2 3 >>> ‘hello‘+‘world‘ ‘helloworld‘
這裏的加運算符對於數字(本例中為整數)和字符串(以及其他類型的序列)都能起作用。假設有個叫做叫做add的函數,它可以將兩個對象相加。那麽可以直接將其定義成上面的形式,對於很多類型的參數都可以用,如下:
參數可以是任何支持加法的對象。
>>> def add(x,y): return x+y >>> add(1,2) 3 >>> add(‘hello.‘,‘world‘) ‘hello.world‘
如果需要編寫打印對象長度消息的函數,則只需對象具有長度(len函數可用)即可。
repr() 函數將對象轉化為供解釋器讀取的形式。
repr用於放置函數的內容;repr函數是多態特性的代表之一---可以對任何東西使用。
>>> def length_message(x): print ("The length of",repr(x),"is",len(x)) #輸出 >>> length_message(‘liulu‘) The length of ‘liulu‘ is 5 >>> length_message(‘hello,world‘) The length of ‘hello,world‘ is 11
封裝
封裝是對全局作用域中其他區域隱藏多余信息的原則。
封裝聽起來有些像多態,因為他們都是 抽象的原則---他們都會幫助處理程序組件而不用過多關心多余細節,就像函數做的一樣。
但是封裝並不等同於多態。多態的可以讓用戶對於不知道是什麽類(或對象類型)的對象進行方法調用,而封裝是可以不用關心對象是如何構建的而直接進行使用。
創建一個對象(通過像調用函數一樣調用類)後,將變量c綁定到該對象上。可以使用setName 和 getName 方法(假設已經有)
>>> c = closedObject() >>> c.setName(‘sir lancelot‘) >>> c.getName() ‘sir lancelot’
繼承
我們不想把同一段代碼寫好幾遍,之前使用的函數避免了這種情況。但現在又有個更微妙的問題。如果已經有了一個類,又想建立一個非常類似的類,只是添加幾個方法。
比如有動物類,我們又想在動物類的基礎上建立鳥類、魚類,哺乳動物類。
創建類
_metaclass_ = type #確定新式類 class Person: def setname(self,name): self.name = name def getname(self): return self,name def greet(self): print ("hello,world!I‘m %s"%self.name) #輸出 >>> liulu = Person() >>> liulu.setname(‘liulu‘) >>> liulu.greet() hello,world!I‘m liulu
應該能說明self的用處了,在調用liulu的setName 和 greet 函數時,liulu自動將自己作為第一個參數傳入函數中----因此形象地命名為self。每個人可能都會有自己的叫法,但是因為它總是對象自身,所以習慣上總是叫做self 。
特性可以在外部訪問
>>> liulu.name ‘liulu‘ >>> liulu.name = ‘lulu‘ >>> liulu.greet() hello,world!I‘m lulu
特性、函數和方法
self參數事實上正是方法和函數的區別。方法將它們的第一個參數綁定到所屬的實例上,因此這個參數可以不必提供。可以將特性綁定到一個普通函數上,這樣就不會有特殊的self參數了。
class bird: song = ‘qiuqiqu~~‘ def sing(self): print (self.song) bird1 = bird() bird1.sing() birdsong = bird1.sing birdsong() #輸出 qiuqiqu~~ qiuqiqu~~
指定超類
子類可以擴展超類的定義。將其他類名寫在class語句後的圓括號內可以指定超類:
Filter 類的用戶在於它可以用作其他類的基類(超類,“java中叫父類”),比如SPAMFilter類,可以將序列中的“SPAM”過濾出來。
class Filter: def init(self): self.blocked = [] def filter(self,sequence): return [x for x in sequence if x not in self.blocked] class SPAMFilter(Filter): #SPAMFilter是Filer的子類 def init(self): #重寫Flier類中的init方法 self.blocked = [‘SPAM‘] #f = Filter() #f.init() #f.filter([1,2,3]) s = SPAMFilter() s.init() print(s.filter([‘SPAM‘,‘SPAMS‘,‘SPAM‘,‘HELLO‘,‘WORLD‘,‘SPAM‘]))
#輸出 [‘SPAMS‘, ‘HELLO‘, ‘WORLD‘]
Filter 是個用於過濾序列的通用類,事實上它不能過濾任何東西:
>>> f = Filter() >>> f.init() >>> f.filter([1,2,3]) [1, 2, 3]
調查繼承
如果想要查看一個類是否是另一個的子類。可以使用內建的issubclass函數:
>>> issubclass(SPAMFilter,Filter)
True
>>> issubclass(Filter,SPAMFilter)
False
python學習記錄(七)