python基礎教程第4版pdf,python中factor函數_Python基礎教程

 2023-10-05 阅读 27 评论 0

摘要:6.4.5 參數收集的逆過程假設有如下函數:def add(x,y): return x+y比如說有個包含由兩個相加的數字組成的元組:params = (1,2)python基礎教程第4版pdf。使用*運算符對參數進行“分配”,不過是在調用而不是在定義時使用:>>> add(*

6.4.5 參數收集的逆過程

假設有如下函數:

def add(x,y): return x+y

比如說有個包含由兩個相加的數字組成的元組:

params = (1,2)

python基礎教程第4版pdf。使用*運算符對參數進行“分配”,不過是在調用而不是在定義時使用:

>>> add(*params)

3

======

同樣,可以使用 雙星號 運算符來處理字典。

假設之前定義了hello_3,那么可以這樣使用:

python3基礎教程廖雪峰云,>>> params = {'name':Sir Robin','greeting':'Well met'}

>>> hello_3(**params)

Well met.Sir Robin

星號只在 定義函數(允許使用不定數目的參數)或者 調用(“分割”字典或者序列)時才有用。

6.5 作用域

在執行x=1賦值語句后,名稱x引用到值1。這就像是使用字典一樣,鍵引用值。當然,變量和所對應的值用的是個“不可見”的字典。

python基礎教程pdf。內建的vars函數可以返回這個字典:

>>> x = 1

>>> scope = vars()

>>> scope['x']

1

>>> scope['x'] += 1

matlab中round函數,>>> x

2

這類“不可見字典”叫做 命名空間 或者 作用域 。除了全局作用域外,每個函數調用都會創建一個新的作用域:

>>> def foo(): x = 42

...

>>> x = 1

table函數?>>> foo()

>>> x

1

這里的foo函數改變(重綁定)了變量x,但是在最后的時候,x并沒有變。這是因為當調用foo的時候,新的命名空間就被創建了,它作用于foo內的代碼塊。賦值語句x=42只在內部作用域(局部命名空間)起作用,所以它并不影響外部(全局)作用域中的x。

函數內的變量被稱為局部變量(local variable),這是與全局變量相反的概念。參數的工作原理類似于局部變量,所以用全局變量的名字作為參數名并沒有問題。

>>> def output(x): print x

round函數。...

>>> x = 1

>>> y = 2

>>> output(y)

2

======

factorial在python的用法、重綁定全局變量:

如果在函數內部將值賦予一個變量,它將會自動成為局部變量——除非告知Python將其聲明為全局變量:

>>> x = 1

>>> def change_global():

global x

x = x + 1

python基礎代碼庫?>>> change_global()

>>> x

2

======

嵌套作用域

Python的函數是可以嵌套的:

matlab的factor函數,def foo():

def bar():

print "Hello,World!"

bar()

函數嵌套有一個很突出的應用,例如需要一個函數“創建”另一個。也就意味著可以像下面這樣(在其他函數內)書寫函數:

def multiplier(factor):

python define函數?def multiplier(number):

return number*factor

returnmultiplyByFactor

一個函數位于另外一個里面,外層函數返回里層函數。也就是說函數本身被返回了,但并沒有被調用。重要的是返回的函數還可以訪問它的定義所在的作用域。換句話說,它“帶著”它的環境(和相關的局部變量)。

每次調用外層函數,它內部的函數都被重新綁定。factor變量每次都有一個新的值。由于Python的嵌套作用域,來自(`multiplier的)外部作用域的這個變量,稍后會被內層函數訪問:

>>> double = multiplier(2)

python的score函數。>>> double(5)

10

>>> triple = multiplier(3)

>>> triple(3)

9

>>> multiplier(5)(4)

python基礎教程菜鳥教程、20

類似multiplayByFactor函數存儲子封閉作用域的行為叫做閉包(closure)。

6.6 遞歸

遞歸的定義(包括遞歸函數定義)包括它們自身定義內容的引用。

關于遞歸,一個類似的函數定義如下:

def recursion():

factor函數?return recursion()

理論上講,上述程序應該永遠地運行下去,然而每次調用函數都會用掉一點內存,在足夠的函數調用發生后(在之前的調用返回后),空間就不夠了,程序會以一個“超過最大遞歸深度”的錯誤信息結束。

這類遞歸就做無窮遞歸(infinite recursion),類似于以while True開始的無窮循環,中間沒有break或者return語句。因為(理論上講)它永遠不會結束。

有用的遞歸函數包含以下幾個部分:

當函數直接返回值時有基本實例(最小可能性問題)

遞歸實例,包括一個或者多個問題較小部分的遞歸調用。

python自學、這里的關鍵就是將問題分解成小部分,遞歸不可能永遠繼續下去,因為它總是以最小可能性問題結束,而這些問題又存儲在基本實例中的。

當每次函數被調用時,針對這個調用的新命名空間會被創建,意味著當函數調用“自身”時,實際上運行的是兩個不同的函數(或者說是同一個函數具有兩個不同的命名空間)。實際上,可以將它想象成和同種類的一個生物進行對話的另一個生物對話。

6.6.1 遞歸經典案例:階乘和冪

計算數n的的階乘:

def factorial(n):

result = n

python教學,for i in range(1,n):

result *= 1

return result

遞歸實現:

1的階乘是1;

大于1的數n的階乘是n乘n-1的階乘。

python基礎教程、def factorial(n):

if n == 1:

return 1

else:

return n * factorial(n-1)

======

計算冪

例子:power(x,n)(x為n的冪次)是x自乘n-1次的結果(所以x用作乘數n次。

def power(x,n):

result = 1

for i in range(n):

result *= x

return result

遞歸實現:

對于任意數字x來說,`power(x,0)是1;

對于任何大于0的書來說,power(x,n)是x乘以(x,n-1)的結果。

def power(x,n):

if n == 0:

return 1

else:

return x * power(x,n-1)

6.6.2 遞歸經典案例:二分法查找

遞歸實現:

如果上下限相同,那么就是數字所在位置,返回;

否則找到兩者的中點(上下限的平均值),查找數字是在左側還是在右側,繼續查找數字所在的那半部分。

def search(sequence,number,lower,upper):

if lower == upper:

assert number == sequence[upper]

return upper

else:

#整數除法//,浮點數除法/

middle = (lower + upper) // 2

if number > sequence[middle]:

return search(sequence,number,middle+1,upper)

else:

return search(sequence,number,lower,middle)

提示:標準庫中的bisect模塊可以非常有效地實現二分查找。

補充:函數式編程

Python在應對“函數式編程”方面有一些有用的函數:map、filter和reduce函數(Python3.0中都被移至fuctools模塊中)。

map和filter在目前版本的Python并非特別有用,并且可以使用列表推導式代替。不過可以使用map函數將序列中的元素全部傳遞給一個函數:

>>> map(str,range(10)) #Equivalent to [str(i) for i in range(10)]

['0','1','2','3','4','5','6','7','8','9']

filter函數可以基于一個返回布爾值的函數對元素進行過濾。

#island 判斷字符變量是否為字母或數字,

#若是則返回非零,否則返回零

>>> def fun(x):

return x.isalnum()

>>> seq = ["foo","x41","?!","***"]

>>> filter(func,seq)

['foo','x41']

本例中,使用列表推導式可以不用專門定義一個函數:

>>> [x for x in seq if x.isalnum()]

['foo','x41']

事實上,還有個叫做lambda表達式的特性,可以創建短小的函數。

>>> filter(lambda x: x.isalnum().seq)

['foo','x41']

=======

reduce函數一般來說不能輕松被列表推導式替代,但是通常用不到這個功能。它會將序列的前兩個元素與給定的函數聯合使用,并且將它們的返回值和第3個元素繼續聯合使用,直到整個序列都處理完畢,并且得到一個最終結果。

可以使用reduce函數加上lambda x,y:x+y(繼續使用相同的數字):

>>> numbers = [72,101,108,108,111,44,32,119,111,114,108,100,33]

>>> reduce(lambda x,y:x+y,numbers)

1161

當然,這里也可以使用內建函數sum。

6.7 小結

抽象。抽象是隱藏多余細節的藝術。定義處理細節的函數可以讓程序更抽象。

函數定義。函數使用def語句定義。它們是由語句組成的塊,可以從“外部世界”獲取值(參數),也可以返回一個或者多個值作為運算的結果。

參數。函數從參數中得到需要的信息,也就是函數調用時設定的變量。Python中有兩類參數:位置參數 和 關鍵數參數。參數在給定默認值時是可選的。

作用域。變量存儲在作用域(也叫作命名空間)中。Python有兩類主要的作用域——全局作用域 和 局部作用域。作用域可以嵌套。

遞歸。 函數可以調用自身即遞歸。一切用遞歸實現的功能都能用循環實現,但是有些時候遞歸函數更易讀。

函數式編程。Python有一些進行函數式編程的機制。包括lambda表達式以及map、filter和reduce函數。

6.7.1 本章的新函數

| 函數 | 描述 |

| ------------- |:-------------|

| map(func,seq[,seq,...])| 對序列中的每個元素應用函數 |

| filter(fuc,seq) | 返回其函數為真的元素的列表 |

| reduce(func,seq[,initial]) | 等同于func(func(func(seq[0],seq[1],se1[2]... |

| sum(seq) | 返回seq所有元素的和 |

| apply(func,args[,kwargs]] | 調用函數,可以提供參數 |

第7章 更加抽象

在面對對象程序設計中,術語對象(object)基本上可以看做數據(特性)以及由一系列可以存取、操作這些數據的方法所組成的集合。使用對象替代全局變量和函數的原因可能有很多,其中對象最重要的優點包括以下幾方面:

多態(Polymorphism):意味著可以對不同類的對象使用同樣的操作,它們會像“被施了魔法一般”工作。

封裝(Encapsulation):對外部世界隱藏對象的工作細節。

繼承(Inheritance):以通用的類為基礎建立專門的類對象。

7.1.1 多態

術語多態的意思是“有多種形式”。多態意味著就算不知道變量所引用的對象類型是什么,還是能它進行操作,而它也會根據對象(或類)類型的不同而表現出不同的行為。

repr函數是多態特性的代表之一,可以對任何東西使用:

def length_message(x):

print "The length of",repr(x),"is",len(x)

>>> length_message('Fnord')

The length of 'Fnord' is 5

>>> length_message([1,2,3])

The length of [1,2,3] is 3

很多函數和運算符都是多態的——你寫的絕大多數程序可能都是,只要使用多態函數和運算符,就會與“多態”發生關聯。事實上,唯一能毀掉多態的就是使用函數顯式地檢查類型,比如type、isinstance以及issubclass函數等等。如果可能的話,應該盡力避免使用這些毀掉多態的方式。真正重要的是如何讓對象按照你所希望的方式工作,不管它是不是真正的類型(或者類)。

7.1.2 封裝

封裝是指向程序中的其他部分隱藏對象的具體實現細節的原則。

但是封裝并不等同于多態,多態可以讓用戶對于不知道什么是類(對象類型)的對象進行方法調用,而封裝是可以不用關心對象是如何構建的而直接進行使用。

基本上,需要將對象進行抽象,調用方法的時候不用關心其他的東西,比如它是否干擾了全局變量。

可以將其作為 特性(attribute) 存儲。特性是作為變量構成對象的一部分,事實上方法更像是綁定到函數上的屬性。

對象有著自己的狀態(state)。對象的狀態由它的特性(比如名稱)來描述。對象的方法可以改變它的特性。所以就像是將一大堆函數(方法)捆在一起,并且給予他們訪問變量(特性)的權力。它們可以在函數調用之間保持保存的值。

7.1.3 繼承

7.2 類和類型

7.2.1 類到底是什么

類是一種對象,所有的對象都屬于某一個類,稱為類的實例(instance)。

當一個對象所屬的類是另外一個對象所屬類的子集時,前者就被稱為后者的 子類(subclass),所以“百靈鳥類”是“鳥類”的子類。相反,“鳥類”是“百靈鳥類”的“超類”(superclass)。但是,在面向程序設計中,子類的關系是隱式的,因為一個類的定義取決于它所支持的方法。類的所有實例都會包含這些方法,所以所有子類的所有實例都有這些方法。定義子類只是個定義更多(也有可能是重載已經存在的)方法的過程。

7.2.2 創建自己的類

7.2.3 特性、函數和方法

事實上,self參數正是方法和參數的區別。方法(更專業一點可以稱為綁定方法)將它們的第一個參數綁定到所屬的實例上,因此無需顯式提供該參數。當然也可以將特性綁定到一個普通函數上,這樣就不會有特殊的self參數了:

>>> class Class:

def method(self):

print 'I hava a self'

>>> def function():

print "I don't..."

>>> instance = Class()

>>> instance.method()

I hava a self!

>>> instance.method =function

>>> instance.method()

I don't...

注意,self參數并不依賴于調用方法的方式,前面使用的是instance.method(實例.方法)的形式,可以隨意使用其他變量引用同一個方法:

>>> class Bird:

song = 'Squaawk!'

def sing(self):

print self.song

>>> bird = Bird()

>>> bird.sing()

Squaawk!

>>> birdsong = bird.sing

>>> birdsong()

Squaawk!

盡管最后一個方法調用看起來與函數調用十分相似,但是變量birdsongs引用綁定方法bird.sing上,也就意味著這還是會對self參數進行訪問(也就是說,它仍舊綁定到類的相同實例上)。

再論私有化

默認情況下,程序可以從外部訪問一個對象的特性:

>>> c.name

'Sir Lancelot'

>>> c.name = 'Sir Gumby'

>>> c.getName()

'Sir Gumby'

為了避免這類事情的發生,應該使用私有(private)特性,這是外部對象無法訪問到,但getName和setName等訪問器(accessor)能夠訪問的特性。

Python并不直接支持私有防暑,為了讓方法或者特性變為私有(從外部無法訪問),只要在它的名字前面加上雙下劃線即可。

class Secretive:

def __inacessible(self):

print "Bet you can't see me.."

def accessible(self):

print "The secret message is:"

self.__inaccessible

現在,__inaccessible從外界是無法訪問的,而在類內部還能使用(比如從accessible)訪問:

>>> s = Secretive()

>>> s.__inaccessible()

Traceback (most recent call last):

File "",;ine 1, in ?

s.__inaccessible()

AttributeError: Secretive instance has no attribute '__inaccessible'

>>> s.accessible()

The secret message is:

Bet you can't see me...

盡管雙下劃線有些奇怪,但是看起來像是其他魚魚中的標準的私有方法。而在類的內部定義中,所有以雙下劃線開始的名字都被“翻譯”成前面加上單下劃線類名的形式。

>>> Secretive._Secret__inaccsible

但實際上還是能夠在類外訪問這些私有方法,盡管不應該這么做:

>>> s._Secretive.__inaccessible

Bet you can't see me..

簡而言之,確保他人不會訪問對象的方法和特性是不可能的,但是這類“名稱變化”是提醒他們不應該訪問這些函數或者特性的強有力信號。

如果不需要使用這種方法但是又想讓其他對象不要訪問內部數據,那么可以使用單下劃線,這不過是個習慣,但的確有實際效果。例如,前面有下劃線的名字都不會被帶星號的import語句(from module import *)導入。

7.2.4 類的命名空間

下面的兩個語句幾乎等價:

def foo(x):return x*x

foo = lambda X:x*x

兩者都創建了返回參數平方的函數,而且都將變量foo綁定到函數上。變量foo可以在全局(模塊)范圍內進行定義,也可處在局部的函數或方法內。定義類時,太陽的事情也會發生,所有位于class語句中的代碼塊都在特殊的命名空間中執行——類命名空間(class namespace)。這個命名空間可由類內所有成員訪問。但并不是所有Python程序員都知道類的定義其實就是執行代碼塊。

7.2.5 指定超類

子類可以拓展超類的定義。將其他類名寫在class語句后的圓括號內可以指定超類。

7.2.6 檢查繼承

如果想要查看一個類是否是另一個的子類,可以使用內建的issubclass函數。

如果想要知道已知類的基類(們),可以直接使用它的特殊特性__base__:

同樣,還能使用isinstance方法檢查一個對象是否是一個類的實例:

7.2.7 多個超類

7.2.8 接口和內省

7.3 一些關于面向對象設計的思考

7.4 小結

第8章 異常

8.1 什么是異常

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/113843.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息