国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

《Python基礎(chǔ)教程》第六章--讀書筆記

AnthonyHan / 2023人閱讀

摘要:第六章抽象本章會(huì)介紹如何將語句組織成函數(shù)。關(guān)鍵字參數(shù)和默認(rèn)值目前為止,我們使用的參數(shù)都是位置參數(shù),因?yàn)樗鼈兊奈恢煤苤匾聦?shí)上比它們的名字更重要。參數(shù)前的星號將所有值放置在同一個(gè)元祖中。函數(shù)內(nèi)的變量被稱為局部變量。

第六章:抽象

本章會(huì)介紹如何將語句組織成函數(shù)。還會(huì)詳細(xì)介紹參數(shù)(parameter)和作用域(scope)的概念,以及遞歸的概念及其在程序中的用途。

懶惰即美德

斐波那契數(shù)列:任何一個(gè)數(shù)都是前兩個(gè)數(shù)之和的數(shù)字序列。

創(chuàng)建函數(shù)

內(nèi)建的callable函數(shù)可以用來判斷函數(shù)是否可調(diào)用:

>>>import math
>>>x = 1
>>>y = math.sqrt
>>>callable(x)
False
>>>callable(y)
True

注:函數(shù)callable在python3.0中不再可用,需要使用表達(dá)式hasattr(func,__call__)代替。
創(chuàng)建斐波那契數(shù)列列表的函數(shù):

def fibs(num):
    result=[0,1]
    for i in range(num-2):
        result.append(result[-2]+result[-1])
    return result
fibs(8)
文檔化函數(shù)

如果想要給函數(shù)寫文檔,讓其他使用函數(shù)人能理解的話,可以加入注釋(以#開頭)。

另外一個(gè)方式就是直接寫上字符串。這類字符串在其他地方可能會(huì)非常有用,比如在def語句后面。

如果在函數(shù)的開頭寫下字符串,他就會(huì)作為函數(shù)的一部分進(jìn)行存儲(chǔ),這成為文檔字符串。

def square(x):
    "Calculate the square of the number"
    return x*x
>>>square.__doc__
"Calculate the square of the number"

注:__DOC__是函數(shù)屬性。第七章會(huì)介紹更多關(guān)于屬性的知識。屬性名中的雙下劃線是個(gè)特殊屬性。這類特殊和“魔法”屬性會(huì)在第9章討論。

help內(nèi)建函數(shù)是非常有用的??梢缘玫疥P(guān)于函數(shù),包括它的文檔字符串信息:

Help on function square in module __main__:
 
square(x)
    Calculate the square of the number
并非真正函數(shù)的函數(shù)

數(shù)學(xué)意義上的函數(shù),總在計(jì)算其參數(shù)后返回點(diǎn)什么。python有些函數(shù)卻并不返回任何東西。

python的函數(shù)就是函數(shù),即便它從學(xué)術(shù)上講并不是函數(shù)。沒有return語句,或者雖然有return語句,但是return后邊乜有跟任何值得函數(shù)不返回值:

def test():
    print "this is michael"
    return
    print "this is not"
>>>x = test()
this is michael
>>>x
>>>print x
None

可以看到,return后邊的語句被跳過了(類似于循環(huán)中的break`語句,不過這里是跳出函數(shù))。

x貌似沒東西,但是其實(shí)有個(gè)很熟悉的值None。所以,所有的函數(shù)的確否返回了東西:當(dāng)不需要它們返回值得時(shí)候,它們返回None??磥韯偛拧坝行┖瘮?shù)并不是真的是函數(shù)”的說法有些不公平了。

參數(shù)魔法

函數(shù)使用起來簡單,創(chuàng)建起來也并不復(fù)雜。但函數(shù)參數(shù)的用法有時(shí)候就有些神奇了。

值從哪里來

參數(shù)錯(cuò)誤的話顯然會(huì)導(dǎo)致失?。ㄒ话銇碚f,這時(shí)候就要用斷言和異常)。

寫在def語句中函數(shù)名后面的變量通常叫做函數(shù)的形參(parameter),而調(diào)用函數(shù)的時(shí)候提供的值是實(shí)參(argument)或者成為參數(shù)。

我能改變參數(shù)嗎?
def try_to_change(n):
    n = "Mr. Michael"
name = "qq"
try_to_change(name)

具體的工作方式類似這樣:

>>>name= "qq"
>>>n = name    #這句的作用基本上等于傳參
>>>n = "qq"
>>>name
"michael"

上面的例子中,由于參數(shù)是字符串(不可變序列),即無法被修改(也就是說只能用新的值覆蓋)。但是,如果將可變的數(shù)據(jù)結(jié)構(gòu)如列表用作參數(shù)的話,那么就有可能改變了。

這里具體例子就不講了,因?yàn)樵倏础秊s高級程序設(shè)計(jì)》時(shí),有相關(guān)類似的概念。值傳遞,引用傳遞。

為什么要改變參數(shù)

使用函數(shù)改變數(shù)據(jù)結(jié)構(gòu)(比如列表或字典)是一種將程序抽象化的好方法。

關(guān)鍵字參數(shù)和默認(rèn)值

目前為止,我們使用的參數(shù)都是位置參數(shù),因?yàn)樗鼈兊奈恢煤苤匾聦?shí)上比它們的名字更重要。

def hello(greeting="hello",name="michael"):
    print "%s,%s"%(greeting,name)
>>>hello("qiuqiu",greeting="hah")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
 in ()
      1 def hello(greeting="hello",name="michael",):
      2     print "%s,%s"%(greeting,name)
----> 3 hello("qiuqiu",greeting="hah")
 
TypeError: hello() got multiple values for keyword argument "greeting"

錯(cuò)誤的意思,按照我自己的理解就是,為參數(shù)greeting賦予了多個(gè)值。這時(shí)候肯定就會(huì)出錯(cuò)了!為什么會(huì)這樣呢?

位置參數(shù)和關(guān)鍵字參數(shù)混合使用的情況,位置參數(shù)是要放在關(guān)鍵字參數(shù)之前的。這里,不是這個(gè)原因。

我猜想 位置參數(shù)和位置肯定有關(guān)系,當(dāng)使用它時(shí),它會(huì)默認(rèn)賦值給它位置對應(yīng)的參數(shù),那么,這里就是greeting。所以呢,這里才會(huì)賦值兩次。做修改:

def hello(name="michael",greeting="hello"):
    print "%s,%s"%(greeting,name)
>>>hello("qiuqiu",greeting="hah")
hah,qiuqiu

默認(rèn)參數(shù)值在函數(shù)被定義時(shí)已經(jīng)計(jì)算出來,而不是在程序運(yùn)行時(shí)。Python程序員經(jīng)常犯的一個(gè)錯(cuò)誤是把可變的數(shù)據(jù)類型(例如列表或者字典)當(dāng)做默認(rèn)參數(shù)值。

收集參數(shù)

有些時(shí)候可以讓用戶提供任意數(shù)量的參數(shù)是很有用的。

def print_params(*params):
    print params

參數(shù)前加*,結(jié)果打印出來是元祖。參數(shù)前的星號將所有值放置在同一個(gè)元祖中??梢哉f是將這些值收集起來。同時(shí),也能和普通參數(shù)聯(lián)合使用:

def print_params2(title,*params):
    print title
    print params
print_params2("test",1,2,3)
test
(1, 2, 3)

星號的意思就是“收集其余的位置參數(shù)”。如果不提供任何供收集的元素,params就是個(gè)空數(shù)組。

print_params2("nothing")  
nothing
()

能不能處理關(guān)鍵字參數(shù)呢?

>>>print_params2("humm",something=42)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
 in ()
----> 1 print_params2("humm",something=42)
 
TypeError: print_params2() got an unexpected keyword argument "something"

使用兩個(gè)**,能處理關(guān)鍵字參數(shù)的“收集操作”。

def print_params3(**params):
    print params
print_params3(x=1,y=2,z=3)
{"y": 2, "x": 1, "z": 3}

返回的是字典而不是元祖了。放在一起看看:

def print_params4(x,y,z=3,*pospar,**keypar):
    print x,y,z
    print pospar
    print keypar
print_params4(1,2,4,"michael",name="michael",age="24")
1 2 4
("michael",)
{"age": "24", "name": "michael"}
參數(shù)收集的逆過程

如何將參數(shù)收集為元祖和字典已經(jīng)討論過了,但是事實(shí)上,如果使用***的話也可以執(zhí)行相反的操作??慈缦吕樱?/p>

#定義函數(shù)
def add(x,y): 
    return x+y

有一個(gè)由兩個(gè)數(shù)字組成的元祖:params=(1,2)

此時(shí)使用*元算符就簡單多了——不過是在調(diào)用而不是在定義時(shí)使用,作用就相反了!
栗子1:

>>>add(*params)
3

栗子2:

def hello3(greeting="hello",name="world"):
    print "%s,%s"%(greeting,name)
params={"name":"michael","greeting":"well done"}
hello3(**params)
well done,michael    #結(jié)果
作用域

什么是變量?可以把它們看作是值的名字。在執(zhí)行x=1賦值語句后,名稱x引用到值1.這就像用字典一樣,鍵引用值,當(dāng)然,變量和所對應(yīng)的值用的是個(gè)“不可見”的字典。實(shí)際上這么說已經(jīng)很接近真實(shí)情況了。內(nèi)建的vars函數(shù)可以返回這個(gè)字典:

>>>x=1
>>>y=1
>>>scope=vars()
>>>scope["x"]
1

vars可以返回全局變量的字典。

locals返回局部變量的字典。

vars函數(shù)官方說明
這類“不可見字典”叫做命名空間或者作用域。

除了全局作用域外,每個(gè)函數(shù)調(diào)用都會(huì)創(chuàng)建一個(gè)新的作用域:

>>>def foo():x=42
>>>x=1
>>>foo()
>>>x
1

當(dāng)調(diào)用foo的時(shí)候,新的命名空間就被創(chuàng)建了,它作用于foo內(nèi)的代碼塊。賦值語句x=42只在內(nèi)部作用域(局部命名空間)起作用,它并不影響外部(全局)作用域中的x。

函數(shù)內(nèi)的變量被稱為局部變量(local variable)。

太痛苦了,這里的知識之前在學(xué)習(xí)JS時(shí)就已經(jīng)了解的挺多,作用域鏈等等。還是記載以下我遺忘的知識好了。不贅述了。

x="michael"
def print_name(x):
    print x+x
print_name("qiuqiu")
qiuqiuqiuqiu    #結(jié)果

這里因?yàn)閰?shù)名和全局變量名重復(fù)了,因此,全局變量就被屏蔽了(如果不重復(fù),是可以讀取到全局變量值的)。我記得在JS中時(shí),也有類似知識點(diǎn),會(huì)逐步向上搜索作用域鏈中的變量值。

那么該怎么達(dá)成效果呢?怎么避免被屏蔽呢?使用globals函數(shù)獲取全局變量值!

x="michael"
def print_name(x):
    print x+globals()["x"]
print_name("qiuqiu")
qiuqiumichael   #結(jié)果

除非告知python將其聲明為全局變量,否則,在函數(shù)內(nèi)的新變量賦值會(huì)自動(dòng)成為局部變量:

x=2
def gl(x):
    global x
    x+=2
    print x
gl(3)
x
File "", line 2
    def gl(x):
SyntaxError: name "x" is local and global

為啥這里出錯(cuò)了呢?因?yàn)?b>x作為形參,是局部變量,而函數(shù)里通過global又定義x是全局變量,因此出現(xiàn)了錯(cuò)誤提示中的錯(cuò)誤。

嵌套作用域(閉包)

python的函數(shù)是可以嵌套的,也就是說可以將一個(gè)函數(shù)放在另一個(gè)里面。

萬萬沒想到,又看到閉包了!python中也是有閉包的嘛,看來各個(gè)語言的機(jī)理概念都大同小異啊~

在其他函數(shù)內(nèi)寫函數(shù):

def multiplier(factor):
    def multiplyByFactor(number):
        return number*factor
    return multiplyByFactor

每次調(diào)用外層函數(shù)(此處的multiplier),它內(nèi)部的函數(shù)都被重新綁定,factor變量每次都有一個(gè)新值!

>>>double=multiplier(2)
>>>double(5)
10
>>>multiplier(5)(4)
20

類似multiplierByFactor函數(shù)存儲(chǔ)子封閉作用域的行為叫做閉包(closure)。

外部作用域的變量一般是不能進(jìn)行重新綁定的。但是python3中,nonlocal關(guān)鍵字被引入。它和global關(guān)鍵字的使用方式類似,可以讓用戶對外部作用域(但并非全局作用域)的變量進(jìn)行賦值。

遞歸(recursion)

遞歸簡單來說就是引用(或者調(diào)用)自身的意思。

def recursion():
    return recursion()

為了深入了解它,讀者應(yīng)該買本計(jì)算機(jī)科學(xué)方面的好書。常用python解釋器也能幫助理解。

無窮遞歸(infinite recursion),類似于以white True開始的無窮循環(huán),中間沒有break或者return語句。

有用的遞歸函數(shù)包括以下部分:

當(dāng)函數(shù)直接返回值時(shí)有基本實(shí)例(最小可能性問題)。

遞歸實(shí)例,包括一個(gè)或者多個(gè)問題最小部分的遞歸調(diào)用。

這里的關(guān)鍵就是將問題分解為小部分,遞歸不能永遠(yuǎn)繼續(xù)下去,因?yàn)樗偸且宰钚】赡苄詥栴}結(jié)束,而這些問題又存貯在基本實(shí)例中的。(就不能講人話嗎?!讀不懂……)

兩個(gè)經(jīng)典:階乘和冪 階乘

可以使用循環(huán):

def factorial(n):
    result=n
    for i in range(1,n):
        result*=i
    return result   

關(guān)鍵在于階乘的定義:

1的階乘是1

大于1的數(shù)n的階乘是n乘n-1的階乘
現(xiàn)在看看遞歸的版本:

def factorial(n):
    if n==1:
        return 1
    else:
        return n*factorial(n-1)

假設(shè)需要計(jì)算冪,就像內(nèi)建函數(shù)pow函數(shù)或者**運(yùn)算符一樣。先看一個(gè)簡單的例子:power(x,n)(x的n次冪)。

def power(x,n):
    result =1
    for i in range(n):
        result*=x
    return result

把它改為遞歸版本:

對于任意數(shù)字x來說,power(x,0)是1; 這就是上面遞歸條件的第一個(gè),最小可能性問題吧

對于任意大于0的數(shù)來說,power(x,n)是x乘以power(x,n-1)的結(jié)果。

理解定義是最困難的部分——實(shí)現(xiàn)起來就簡單了。

def power(x,n):
    if n==0:
        return 1
    else:
        return x*power(x,n-1)

提示:如果函數(shù)或者算法很復(fù)雜而且難懂的話,在實(shí)現(xiàn)前用自己的話明確一下定義是很有幫助的。

函數(shù)式編程

python在應(yīng)對“函數(shù)式編程”方面有一些有用的函數(shù):

map

使用map函數(shù)將序列中的元素全部傳遞給函數(shù)

>>>map(str,range(10))    #Equivalent to [str(i) for i in range(10)]
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

map函數(shù):

Apply function to every item of iterable and return a list of the results.

filter

filter函數(shù)可以基于一個(gè)返回布爾值的函數(shù)對元素進(jìn)行過濾:

def func(x):
    return x.isalnum()

>>>seq=["foo","x41","?!","***"]
>>>filter(func,seq)
["foo","x41"]

Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)]
str.isalpha()
Return true if all characters in the string are alphabetic and there is at least one character, false otherwise.

本章小結(jié)

這章的知識確實(shí)有點(diǎn)多啊,遞歸一直不是特別靈活運(yùn)用,或許真該找本書看看。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/45411.html

相關(guān)文章

  • 流暢的python讀書筆記-六章-使用一等函數(shù)實(shí)現(xiàn)設(shè)計(jì)模式

    摘要:在復(fù)雜的情況下,需要具體策略維護(hù)內(nèi)部狀態(tài)時(shí),可能需要把策略和享元模式結(jié)合起來。函數(shù)比用戶定義的類的實(shí)例輕量,而且無需使用享元模式,因?yàn)楦鱾€(gè)策略函數(shù)在編譯模塊時(shí)只會(huì)創(chuàng)建一次。 一等函數(shù)實(shí)現(xiàn)設(shè)計(jì)模式 經(jīng)典的策略模式定義 定義一系列算法,把它們一一封裝起來,并且使它們可以相互替換。本模式使得算法可以獨(dú)立于使用它的客戶而變化。 案例 假如一個(gè)網(wǎng)店制定了下述折扣規(guī)則。 有 1000 或以上積分...

    cnsworder 評論0 收藏0
  • 《javascript高級程序設(shè)計(jì)》六章 讀書筆記 之 javascript對象的幾種創(chuàng)建方式

    摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對象的方法和的作用都是在某個(gè)特殊對象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別適用情境可以在特殊的情況下用來為對象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會(huì)有很多重復(fù)代碼,在此基礎(chǔ)上改進(jìn)showImg(https://segmentfault.com/img/bVbmKxb?w=456&...

    xiaotianyi 評論0 收藏0
  • 高程讀書筆記 六章 面向?qū)ο蟪绦蛟O(shè)計(jì)

    摘要:創(chuàng)建一個(gè)新對象將構(gòu)造函數(shù)的作用域賦給新對象因此就指向了這個(gè)新對象執(zhí)行構(gòu)造函數(shù)中的代碼為這個(gè)新對象添加屬性返回新對象。 本章內(nèi)容 理解對象屬性 理解并創(chuàng)建對象 理解繼承 ECMA-262把對象定義為:無序?qū)傩缘募希鋵傩钥梢园局?、對象或者函?shù) 理解對象 創(chuàng)建對象 創(chuàng)建自定義對象的最簡單方式就是創(chuàng)建一個(gè)Object的實(shí)例,再為它添加屬性和方法。 var person = new...

    468122151 評論0 收藏0
  • 《java 8 實(shí)戰(zhàn)》讀書筆記 -六章 用流收集數(shù)據(jù)

    摘要:分區(qū)函數(shù)返回一個(gè)布爾值,這意味著得到的分組的鍵類型是,于是它最多可以分為兩組是一組,是一組。當(dāng)遍歷到流中第個(gè)元素時(shí),這個(gè)函數(shù)執(zhí)行時(shí)會(huì)有兩個(gè)參數(shù)保存歸約結(jié)果的累加器已收集了流中的前個(gè)項(xiàng)目,還有第個(gè)元素本身。 一、收集器簡介 把列表中的交易按貨幣分組: Map transactionsByCurrencies = transactions.stream().collect(groupi...

    Airy 評論0 收藏0
  • 《javascript高級程序設(shè)計(jì)》六章 讀書筆記 之 javascript繼承的6種方法

    摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對應(yīng)的是接口繼承,由于script中函數(shù)沒有簽名,所以無法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...

    孫吉亮 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<