高階函數就是能夠把函數當成參數傳遞的函數就是高階函數,換句話說如果一個函數的參數是函數,那么這個函數就是一個高階函數。
站在用戶的角度思考問題,與客戶深入溝通,找到西盟網站設計與西盟網站推廣的解決方案,憑借多年的經驗,讓設計與互聯網技術結合,創造個性化、用戶體驗好的作品,建站類型包括:網站設計、網站建設、企業官網、英文網站、手機端網站、網站推廣、申請域名、網絡空間、企業郵箱。業務覆蓋西盟地區。
高階函數可以是你使用 def 關鍵字自定義的函數,也有Python系統自帶的內置高階函數。
我們下面的例子中,函數 senior 的參數中有一個是函數,那么senior就是一個高階函數;函數 tenfold 的參數不是函數,所以tenfold就只是一個普通的函數。
function:函數,可以是 自定義函數 或者是 內置函數;
iterable:可迭代對象,可迭代性數據。(容器類型數據和類容器類型數據、range對象、迭代器)
把可迭代對象中的數據一個一個拿出來,然后放在到指定的函數中做處理,將處理之后的結果依次放入迭代器中,最后返回這個迭代器。
將列表中的元素轉成整型類型,然后返回出來。
列表中的每一個數依次乘 2的下標索引+1 次方。使用自定義的函數,配合實現功能。
參數的意義和map函數一樣
filter用于過濾數據,將可迭代對象中的數據一個一個的放入函數中進行處理,如果函數返回值為真,將數據保留;反之不保留,最好返回迭代器。
保留容器中的偶數
參數含義與map、filter一致。
計算數據,將可迭代對象的中的前兩個值放在函數中做出運算,得出結果在和第三個值放在函數中運算得出結果,以此類推,直到所有的結果運算完畢,返回最終的結果。
根據功能我們就應該直到,reduce中的函數需要可以接收兩個參數才可以。
將列表中的數據元素組合成為一個數,
iterable:可迭代對象;
key:指定函數,默認為空;
reverse:排序的方法,默認為False,意為升序;
如果沒有指定函數,就單純的將數據安札ASCII進行排序;如果指定了函數,就將數據放入函數中進行運算,根據數據的結果進行排序,返回新的數據,不會改變原有的數據。
注意,如果指定了函數,排序之后是根據數據的結果對原數據進行排序,而不是排序計算之后的就結果數據。
將列表中的數據進行排序。
還有一點就是 sorted 函數可以將數據放入函數中進行處理,然后根據結果進行排序。
既然有了列表的內置函數sort,為什么我們還要使用sorted函數呢?
高階函數就是將函數作為參數的函數。
文章來自
將函數作為參數傳入,這樣的函數稱為高階函數。 函數式編程就是指這種高度抽象的編程范式。
變量可以指向函數,函數的參數能接收變量,那么一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。如下所示:
map(fun, lst),將傳入的函數變量func作用到lst變量的每個元素中,并將結果組成新的列表返回。
定義一個匿名函數并調用,定義格式如--lambda arg1,arg2…:表達式
reduce把一個函數作用在一個序列[x1, x2, x3, …]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算。
filter() 函數用于過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。
閉包的定義?閉包本質上就是一個函數
如何創建閉包?
如何使用閉包?典型的使用場景是裝飾器的使用。
global與nonlocal的區別:
簡單的使用如下:
偏函數主要輔助原函數,作用其實和原函數差不多,不同的是,我們要多次調用原函數的時候,有些參數,我們需要多次手動的去提供值。
而偏函數便可簡化這些操作,減少函數調用,主要是將一個或多個參數預先賦值,以便函數能用更少的參數進行調用。
我們再來看一下偏函數的定義:
類func = functools.partial(func, *args, **keywords)
我們可以看到,partial 一定接受三個參數,從之前的例子,我們也能大概知道這三個參數的作用。簡單介紹下:
總結
本文是對Python 高階函數相關知識的分享,主題內容總結如下:
1、Python類型操作符和內建函數總結
表4.5列出了所有操作符和內建函數,其中操作符順序是按優先級從高到低排列的。同一種灰度的操作符擁有同樣的優先級。注意在operator模塊中有這些(和絕大多數Python)操作符相應的同功能的函數可供使用。
表4.5 標準類型操作符和內建函數
操作符/函數
描 述
結 果a
字符串表示
``
對象的字符串表示
str
內建函數
cmp(obj1, obj2)
比較兩個對象
int
repr(obj)
對象的字符串表示
str
str(obj)
對象的字符串表示
str
type(obj)
檢測對象的類型
type
值比較
小于
bool
大于
bool
=
小于或等于
bool
=
大于或等于
bool
==
等于
bool
!=
不等于
bool
不等于
bool
對象比較
is
是
bool
is not
不是
bool
布爾操作符
not
邏輯反
bool
and
邏輯與
bool
or
邏輯或
bool
2、Python數值類型操作符和內建函數
一、工廠函數
數值工廠函數總結類(工廠函數) 操作
bool(obj) b 返回obj對象的布爾值,也就是 obj.__nonzero__()方法的返回值。
int(obj, base=10) 返回一個字符串或數值對象的整數表 示, 類似string.atoi();
從Python 1.6起, 引入了可選的進制參數。
long(obj, base=10) 返回一個字符或數據對象的長整數表 示,類似string.atol(),
從Python1.6起, 引入了可選的進制參數 float(obj) ,
返回一個字符串或數據對象的浮點數 表示,類似string.atof()。
complex(str) or返回一個字符串的復數表示,或 者根據給定的實數,
complex(real, imag=0.0) (及一個可選 的虛數部分)生成一個復數對象。
二、內建函數
1、分類
Python 有五個運算內建函數用于數值運算:
abs(num), coerce(num1,num2), divmod(num1,num2), pow(num1,num2,mod=1)和 round(flt,ndig=0)
其中abs()返回給定參數的絕對值。如果參數是一個復數, 那么就返回math.sqrt(num.real2 + num.imag2).
coerce()是一個數據類型轉換函數,不過它的行為更像一個運算符.數coerce()為程序員提供了不依賴Python 解釋器,而是自定義兩個數值類型轉換的方法。對一種新創建的數值類型來說, 這個特性非常有用.函數coerce()僅返回一個包含類型轉換完畢的兩個數值元素的元組.
divmod()內建函數把除法和取余運算結合起來, 返回一個包含商和余數的元組.對整數來說,它的返回值就是地板除和取余操作的結果.對浮點數來說,返回的商部分是math.floor(num1/num2),對復數來說,商部分是ath.floor((num1/num2).real).
pow()它和雙星號 (**)運算符都可以進行指數運算.不過二者的區別并不僅僅在于一個是運算符,一個是內建函數.在Python 1.5 之前,并沒有 ** 運算符,內建函數pow()還接受第三個可選的參數,一個余數參數.如果有這個參數的, pow() 先進行指數運算,然后將運算結果和第三個參數進行取余運算.這個特性主要用于密碼運算,并且比 pow(x,y) % z 性能更好, 這是因為這個函數的實現類似于C 函數pow(x,y,z).
round()用于對浮點數進行四舍五入運算。它有一個可選的小數位數參數.如果不提供小數位參數, 它返回與第一個參數最接近的整數(但仍然是浮點類型).第二個參數告訴round 函數將結果精確到小數點后指定位數.
2、函數int()/round()/math.floor()它們之間的不同之處:
函數 int()直接截去小數部分.(返回值為整數)
函數 floor() 得到最接近原數但小于原數的整數.(返回值為浮點數)
函數 round() 得到最接近原數的整數.(返回值為浮點數)
3、進制轉換函數:
返回字符串表示的8 進制和16 進制整數,它們分別是內建函數:
oct()和 hex(). oct(255)='0377'/hex(255)='0xff'
函數chr()接受一個單字節整數值(0到255),返回一個字符串(ASCII),其值為對應的字符.chr(97)='a'
函數ord()則相反,它接受一個字符(ASCII 或 Unicode),返回其對應的整數值.ord('A')=65
3、Python字符串函數
(一)標準類型操作符和標準內建函數
1)、標準類型操作符
,,=,=,==,!=,對象值得比較
注:做比較時字符串是按ASCII值的大小來比較的
is 對象身份比較
and,or,not 布爾類型
2)標準內建函數
type(obj)
cmp(obj1,obj2)
str(obj)和repr(obj) 或反引號運算符(``) 可以方便的以字符串的方式獲取對象的
內容、類型、數值屬性等信息。str()函數得到的字符串可讀性好, 而repr()函數得到的字符
串通常可以用來重新獲得該對象, 通常情況下 obj == eval(repr(obj)) 這個等式是成立的
isinstance(obj,type) 判斷對象的類型
(二)序列操作
1、序列操作
字符串屬于序列對象,可以使用所有序列的操作和函數
切片 [] [:] [::]
簡單總結:
*索引(S[i])獲取特定偏移的元素。
——第一個元素偏移為0
——(S[0])獲取第一個元素。
——負偏移索引意味著從最后或右邊反向進行計數
——(S[-2])獲取倒數第二個元素(就像S[len(s)-2]一樣
*分片[S[i:j]提取對應的部分作為一個序列
——右邊界不包含在內
——分片的邊界默認為0和序列的長度,如果沒有給出的話S[:]
——(S[1:3])獲取了從偏移為1,直到但不包括偏移為3的元素
——(S[1:])獲取從偏移為1到末尾之間的元素
——(S[:3])獲取從偏移為0直到但不包括偏移為3的元素
——(S[:-1])獲取從偏移為0直到但不包括最后一個元素之間的元素
——(S[:])獲取從偏移為0到末尾之間的元素,這有效地實現了頂層S拷貝
拷貝了一個相同值,但是是不同內存區域的對象。對象字符串這樣不可變的對象不是很有用,但是對于可以實地修改的對象來說很有用。
比如列表。
擴展分片:第三個限制值 【步進】
完整形式:X[I:J:K]:這標識索引X對象的元素,從偏移為I直到J-1,每隔K元素索引一次。第三個限制值,K,默認為1
實例
Python Code
1
2
3
4
5
S='abcdefghijk'
S[1:10]
'bcdefghij'
S[1:10:2]
'bdfhj
也可以使用負數作為步進。
分片表達式
Python Code
1
2
"hello"[::-1]
'olleh'
通過負數步進,兩個邊界的意義實際上進行了反轉。
3、成員操作符 in ,not in
返回布爾值True 或False
可以使用string模塊來判斷輸入字符的合法性,可見成品中的idcheck.py
4、字符串連接
+ 連接字符串 ‘name’+' '+'jin'
字符串格式化 '%s %s' % ('name','jin')
join()方法 ' '.join(('name','jin')) ' '.join(['name','jin'])
5、刪除清空字符串
del aString
aString=''
(三)、序列函數
序列類型函數
len(str) 返回字串的長度
enumerate(iter):接受一個可迭代對象作為參數,返回一個enumerate
max(str)/min(str):max()和min()函數對其他的序列類型可能更有用,但對于string類型它們能很好地運行,返回最大或者最小的字符(按照ASCII 碼值排列),
zip([it0, it1,... itN]) 返回一個列表,其第一個元素是it0,it1,...這些元素的第一個元素組成的一個元組,第二個...,類推.
reversed(seq)c 接受一個序列作為參數,返回一個以逆序訪問的迭代器(PEP 322)
sorted(iter,func=None,key=None,reverse=False) 接受一個可迭代對象作為參數,返回一個有序的列表;可選參數func,key 和reverse 的含義跟list.sort()內建函數的參數含義一樣.
注意:
sorted等需要在原處修改的函數無法用在字符串對象,但可以產生新的對象
sum處理的對象是數字,不能用在字符串
sorted(s)
['a', 'e', 'e', 'g', 'g', 'g', 'o']
(四)只適合于字符串類型的函數
1)raw_input()函數
內建的raw_input()函數使用給定字符串提示用戶輸入并將這個輸入返回,下面是一個使
用raw_input()的例子:
user_input = raw_input("Enter your name: ")
prin user_input
2)str() and unicode()
str()和unicode()函數都是工廠函數,就是說產生所對應的類型的對象.它們接受一個任
意類型的對象,然后創建該對象的可打印的或者Unicode 的字符串表示. 它們和basestring 都
可以作為參數傳給isinstance()函數來判斷一個對象的類型
3)chr(), unichr(), and ord()
chr()函數用一個范圍在range(256)內的(就是0 到255)整數做參數,返回一個對應的字符.unichr()跟它一樣,只不過返回的是Unicode 字符
ord()函數是chr()函數(對于8 位的ASCII 字符串)或unichr()函數(對于Unicode 對象)
的配對函數,它以一個字符(長度為1 的字符串)作為參數,返回對應的ASCII 數值,或者Unicode
數值,如果所給的Unicode 字符超出了你的Python 定義范圍,則會引發一個TypeError 的異常
(五)、只適用于字符串的操作符
1、格式化操作符 %
字符串格式化符號
格式化字符 轉換方式
%c 轉換成字符(ASCII 碼值,或者長度為一的字符串)
%ra 優先用repr()函數進行字符串轉換
%s 優先用str()函數進行字符串轉換
%d / %i 轉成有符號十進制數
%ub 轉成無符號十進制數
%ob 轉成無符號八進制數
%xb/%Xb (Unsigned)轉成無符號十六進制數(x/X 代表轉換后的十六進制字符的大
小寫)
%e/%E 轉成科學計數法(e/E 控制輸出e/E)
%f/%F 轉成浮點數(小數部分自然截斷)
%g/%G %e 和%f/%E 和%F 的簡寫
%% 輸出%
格式化操作符輔助指令
符號 作用
* 定義寬度或者小數點精度
- 用做左對齊
+ 在正數前面顯示加號( + )
sp 在正數前面顯示空格
# 在八進制數前面顯示零('0'),在十六進制前面顯示'0x'或者'0X'(取決于
用的是'x'還是'X')
0 顯示的數字前面填充‘0’而不是默認的空格
% '%%'輸出一個單一的'%'
(var) 映射變量(字典參數)
m.n m 是顯示的最小總寬度,n 是小數點后的位數(如果可用的話)
2、字符串模板: 更簡單的替代品
由于新式的字符串Template 對象的引進使得string 模塊又重新活了過來,Template 對象
有兩個方法,substitute()和safe_substitute().前者更為嚴謹,在key 缺少的情況下它會報一
個KeyError 的異常出來,而后者在缺少key 時,直接原封不動的把字符串顯示出
3、原始字符串操作符( r/R )
字符串抑制轉義r'帶特殊符號的字串'
myfile=open(r'C:\new\text.data','w')
4、Unicode 字符串操作符( u/U )
u'abc' U+0061 U+0062 U+0063
u'\u1234' U+1234
u'abc\u1234\n' U+0061 U+0062 U+0063 U+1234 U+0012
(六)字符串對象的方法:
1、刪減
T2.lstrip() 移除字符串前面字符(默認空格),返回字符串
T2.rstrip() 移除字符串后面字符(默認空格),返回字符串
T2.strip() 移除字符串前后面空格,返回字符串 默認空格,可以其他字符 S.strip('"')
2、切割
partition(sep),
rpartition(sep),
splitlines([keepends]),#把S按照行分割符分為一個list,keepends是一個bool值,如果為真每行后而會保留行分割符
split([sep [,maxsplit]]),#以sep為分隔符,把S分成一個list。maxsplit表示分割的次數。默認的分割符為空白字符
rsplit([sep[,maxsplit]]) #從右到左切割
備注:
partition()函數族是2.5版本新增的方法。它接受一個字符串參數,并返回一個3個元素的 tuple 對象。
如果sep沒出現在母串中,返回值是 (sep, ‘’, ‘’);
否則,返回值的第一個元素是 sep 左端的部分,第二個元素是 sep 自身,第三個元素是 sep 右端的部分。
S.partition(';')
('', ';', ' generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n')
參數 maxsplit 是分切的次數,即最大的分切次數,所以返回值最多有 maxsplit+1 個元素。
s.split() 和 s.split(‘ ‘)的返回值不盡相同
' hello world!'.split()
['hello', 'world!']
' hello world!'.split(' ')
['', '', 'hello', '', '', 'world!']
S.split('\n',3)
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n']
超過最大切割個數后面的全部為一個元素
按行切割
S
'; generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n'
S.splitlines()
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2', 'nameserver 178.79.131.110', 'nameserver 202.96.199.133']
產生差異的原因在于當忽略 sep 參數或sep參數為 None 時與明確給 sep 賦予字符串值時 split() 采用兩種不同的算法。
對于前者,split() 先去除字符串兩端的空白符,然后以任意長度的空白符串作為界定符分切字符串
即連續的空白符串被當作單一的空白符看待;
對于后者則認為兩個連續的 sep 之間存在一個空字符串。因此對于空字符串(或空白符串),它們的返回值也是不同的:
''.split()
[]
''.split(' ')
['']
3、變形
lower(),#全部小寫
upper(),#全部小寫
capitalize(),#首字母大寫
swapcase(),#大小寫交換
title()#每個單詞第一個大寫,其他小寫
備注
因為title() 函數并不去除字符串兩端的空白符也不會把連續的空白符替換為一個空格,
所以建議使用string 模塊中的capwords(s)函數,它能夠去除兩端的空白符,再將連續的空白符用一個空格代替。
Python Code
1
2
3
4
' hello world!'.title()
' Hello World!'
string.capwords(' hello world!')
'Hello World!'
4、連接
join(seq)
join() 函數的高效率(相對于循環相加而言),使它成為最值得關注的字符串方法之一。
它的功用是將可迭代的字符串序列連接成一條長字符串,如:
conf = {'host':'127.0.0.1',
... 'db':'spam',
... 'user':'sa',
... 'passwd':'eggs'}
';'.join("%s=%s"%(k, v) for k, v in conf.iteritems())
'passswd=eggs;db=spam;user=sa;host=127.0.0.1'
S=''.join(T) #使用空字符串分割把字符列表轉換為字符串
5、查找
count( sub[, start[, end]]),#計算substr在S中出現的次數
find( sub[, start[, end]]),#返回S中出現sub的第一個字母的標號,如果S中沒有sub則返回-1。start和end作用就相當于在S[start:end]中搜索
index( substr[, start[, end]]),#與find()相同,只是在S中沒有substr時,會返回一個運行時錯誤
rfind( sub[, start[,end]]),#返回S中最后出現的substr的第一個字母的標號,如果S中沒有substr則返回-1,也就是說從右邊算起的第一次出現的substr的首字母標號
rindex( sub[, start[, end]])
T2.find('ie') 字符串方法調用:搜索
find()----找到的第一個符合字符的index
rfind()-----找到最后一個符合的字符的index
備注:
find()函數族找不到時返回-1,index()函數族則拋出ValueError異常。
另,也可以用 in 和 not in 操作符來判斷字符串中是否存在某個模板
6、替換
replace(old, new[,count]),#把S中的oldstar替換為newstr,count為替換次數。這是替換的通用形式,還有一些函數進行特殊字符的替換
translate(table[,deletechars]) #使用上面的函數產后的翻譯表,把S進行翻譯,并把deletechars中有的字符刪掉
備注:
replace()函數的 count 參數用以指定最大替換次數
translate() 的參數 table 可以由 string.maketrans(frm, to) 生成
translate() 對 unicode 對象的支持并不完備,建議不要使用
7、判定
isalnum(),#是否全是字母和數字,并至少有一個字符
isalpha(),是否全是字母,并至少有一個字符
isdigit(),是否全是數字,并至少有一個字符 ,如果是全數字返回True,否則返回False
islower(),#S中的字母是否全是小寫
isupper(),#S中的字母是否是大寫
isspace(),#是否全是空白字符,并至少有一個字符
istitle(),S是否是首字母大寫的
startswith(prefix[, start[, end]]), #是否以prefix開頭
endswith(suffix[,start[, end]]),#以suffix結尾
備注:
這些函數都比較簡單,顧名知義。需要注意的是*with()函數族可以接受可選的 start, end 參數,善加利用,可以優化性能。
另,自 Py2.5 版本起,*with() 函數族的 prefix 參數可以接受 tuple 類型的實參,當實參中的某人元素能夠匹配,即返回 True。
8、填充
字符串在輸出時的對齊:
center(width[, fillchar]), 字符串中間對齊
ljust(width[, fillchar]), 字符串左對齊,不足部分用fillchar填充,默認的為空格
rjust(width[, fillchar]), 字符串右對齊,不足部分用fillchar填充,默認的為空格
zfill(width), 把字符串變成width長,并在右對齊,不足部分用0補足
expandtabs([tabsize])把字符串中的制表符(tab)轉換為適當數量的空格。
fillchar 參數指定了用以填充的字符,默認為空格
zfill的z為zero的縮寫,顧名思義,是以字符0進行填充,用于數值輸出
expandtabs()的tabsize 參數默認為8。它的功能是把字符串中的制表符(tab)轉換為適當數量的空格。
9、編碼
encode([encoding[,errors]]),
decode([encoding[,errors]])
這是一對互逆操作的方法,用以編碼和解碼字符串。因為str是平臺相關的,它使用的內碼依賴于操作系統環境,
而unicode是平臺無關的,是Python內部的字符串存儲
在Python中,訪問一個屬性的優先級順序按照如下順序:
1.類屬性
2.數據描述符
3.實例屬性
4.非數據描述符
5.__getattr__()方法。這個方法的完整定義如下所示:
[python] view plain copy
def __getattr__(self,attr) :#attr是self的一個屬性名
pass;
先來闡述下什么叫數據描述符。
數據描述符是指實現了__get__,__set__,__del__方法的類屬性(由于Python中,一切皆是對象,所以你不妨把所有的屬性也看成是對象)
PS:個人覺得這里最好把數據描述符等效于定義了__get__,__set__,__del__三個方法的接口。
闡述下這三個方法:
__get__的標準定義是__get__(self,obj,type=None),它非常接近于JavaBean的get
第一個函數是調用它的實例,obj是指去訪問屬性所在的方法,最后一個type是一個可選參數,通常為None(這個有待于進一步的研究)
例如給定類X和實例x,調用x.foo,等效于調用:
type(x).__dict__["foo"].__get__(x,type(x))
調用X.foo,等效于調用:
type(x).__dict__["foo"].__get__(None,type(x))
第二個函數__set__的標準定義是__set__(self,obj,val),它非常接近于JavaBean的set方法,其中最后一個參數是要賦予的值
第三個函數__del__的標準定義是__del__(self,obj),它非常接近Java中Object的Finailize()方法,指
Python在回收這個垃圾對象時所調用到的析構函數,只是這個函數永遠不會拋出異常。因為這個對象已經沒有引用指向它,拋出異常沒有任何意義。
接下來,我們來一一比較這些優先級.
首先來看類屬性
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class A(object):
foo=3
print A.foo
a=A()
print a.foo
a.foo=4
print a.foo
print A.foo
上面這段代碼的輸出如下:
3
3
4
3
從輸出可以看到,當我們給a.foo賦值的時候,其實與類實例的那個foo是沒有關系的。a.foo=4 這句話給a對象增加了一個屬性叫foo。其值是4。
最后兩個語句明確的表明了,我們輸出a.foo和A.foo的值,他們是不同的。
但是為什么a=A()語句后面的print
a.foo輸出了3呢?這是因為根據搜索順序找到了類屬性。當我們執行a.foo=4的時候,我們讓a對象的foo屬性指向了4這個對象。但是并沒有改變
類屬性foo的值。所以最后我們print A.foo的時候,又輸出了3。
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class A(object):
foo=3
a=A()
a.foo=4
print a.foo
del a.foo
print a.foo
上面的代碼,我給a.foo賦值為4,在輸出一次之后就del了。兩次輸出,第一次輸出的是a對象的屬性。第二次是類屬性。不是說類屬性的優先級比
實例屬性的高嗎。為啥第一次輸出的是4而不是3呢?還是上面解釋的原因。因為a.foo與類屬性的foo只是重名而已。我們print
a.foo的時候,a的foo指向的是4,所以輸出了4。
------------------------------------
然后我們來看下數據描述符這一全新的語言概念。按照之前的定義,一個實現了__get__,__set__,__del__的類都統稱為數據描述符。我們來看下一個簡單的例子。
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None):
pass
def __set__(self,obj,val):
pass
def __del__(self,obj):
pass
class A(object):
foo=simpleDescriptor()
print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo
上面例子的輸出結果如下:
[plain] view plain copy
{'__dict__': attribute '__dict__' of 'A' objects, '__module__': '__main__', 'foo': __main__.simpleDescriptor object at 0x005511B0, '__weakref__': attribute '__weakref__' of 'A' objects, '__doc__': None}
None
None
None
從輸出結果看出,print語句打印出來的都是None。這說明a.foo都沒有被賦值內容。這是因為__get__函數的函數體什么工作都沒有做。直接是pass。此時,想要訪問foo,每次都沒有返回內容,所以輸出的內容就是None了。
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None):
return "hi there"
def __set__(self,obj,val):
pass
def __del__(self,obj):
pass
class A(object):
foo=simpleDescriptor()
print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo
把__get__函數實現以下,就可以得到如下輸出結果:
[plain] view plain copy
{'__dict__': attribute '__dict__' of 'A' objects, '__module__': '__main__', 'foo': __main__.simpleDescriptor object at 0x00671190, '__weakref__': attribute '__weakref__' of 'A' objects, '__doc__': None}
hi there
hi there
hi there
為了加深對數據描述符的理解,看如下例子:
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = 13;
print a.foo;
上面代碼的輸出是
16
6
第一個16為我們在對a.foo賦值的時候,人為的將13加上3后作為foo的值,第二個6是我們在返回a.foo之前人為的將它減去了10。
所以我們可以猜測,常規的Python類在定義get,set方法的時候,如果無特殊需求,直接給對應的屬性賦值或直接返回該屬性值。如果自己定義類,并且繼承object類的話,這幾個方法都不用定義。
-----------------
在這里看一個題外話。
看代碼
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
if isinstance(val,str):
assert False,"int needed! but get str"
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = "13";
print a.foo;
上面代碼在__set__ 函數中檢查了參數val,如果val是str類型的,那么要報錯。這就實現了我們上一篇文章中要實現的,在給屬性賦值的時候做類型檢查的功能。
-----------------------------------------------
下面我們來看下實例屬性和非數據描述符。
[python] view plain copy
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class B(object):
foo = 1.3
b = B()
print b.__dict__
b.bar = 13
print b.__dict__
print b.bar
上面代碼輸出結果如下:
{}
{'bar': 13}
13
那么什么是非數據描述符呢?
簡單的說,就是沒有實現get,set,del三個方法的所有類。
讓我們任意看一個函數的描述:
def call():
pass
執行print dir(call)會得到如下結果:
[plain] view plain copy
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
先看下dir的幫助。
dir列出給定對象的屬性或者是從這個對象能夠達到的對象。
回到print dir(call)方法的輸出,看到,call方法,有輸出的那么多個屬性。其中就包含了__get__函數。但是卻沒有__set__和__del__函數。所以所有的類成員函數都是非數據描述符。
看一個實例數據掩蓋非數據描述符的例子:
[python] view plain copy
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type
class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo
看輸出:
('get', __main__.simpleDescriptor object at 0x02141190,
__main__.D object at 0x025CAF50, class '__main__.D')
15
可見,實例數據掩蓋了非數據描述符。
如果改成數據描述符,那么就不會被覆蓋了。看下面:
[python] view plain copy
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type
def __set__(self,obj,type=None) :
pass
def __del__(self,obj,type=None) :
pass
class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo
代碼的輸出如下:
[plain] view plain copy
('get', __main__.simpleDescriptor object at 0x01DD1190, __main__.D object at 0x0257AF50, class '__main__.D')
('get', __main__.simpleDescriptor object at 0x01DD1190, __main__.D object at 0x0257AF50, class '__main__.D')
由于是數據描述符,__set __函數體是pass,所以兩次輸出都是同樣的內容。
最后看下__getatrr__方法。它的標準定義是:__getattr__(self,attr),其中attr是屬性名
1. 運算優先級
括號、指數、乘、除、加、減
2
如果你使用了非 ASCII 字符而且碰到了編碼錯誤,記得在最頂端加一行 # -- coding: utf-8 --
3. Python格式化字符
使用更多的格式化字符。例如 %r 就是是非常有用的一個,它的含義是“不管什么都打印出來”。
%s -- string
%% 百分號標記 #就是輸出一個%
%c 字符及其ASCII碼
%s 字符串
%d 有符號整數(十進制)
%u 無符號整數(十進制)
%o 無符號整數(八進制)
%x 無符號整數(十六進制)
%X 無符號整數(十六進制大寫字符)
%e 浮點數字(科學計數法)
%E 浮點數字(科學計數法,用E代替e)
%f 浮點數字(用小數點符號)
%g 浮點數字(根據值的大小采用%e或%f)
%G 浮點數字(類似于%g)
%p 指針(用十六進制打印值的內存地址)
%n 存儲輸出字符的數量放進參數列表的下一個變量中
%c 轉換成字符(ASCII 碼值,或者長度為一的字符串)
%r 優先用repr()函數進行字符串轉換(Python2.0新增)
%s 優先用str()函數進行字符串轉換
%d / %i 轉成有符號十進制數
%u 轉成無符號十進制數
%o 轉成無符號八進制數
%x / %X (Unsigned)轉成無符號十六進制數(x / X 代表轉換后的十六進制字符的大小寫)
%e / %E 轉成科學計數法(e / E控制輸出e / E)
%f / %F 轉成浮點數(小數部分自然截斷)
%g / %G : %e和%f / %E和%F 的簡寫
%% 輸出%
輔助符號 說明
* 定義寬度或者小數點精度
- 用做左對齊
+ 在正數前面顯示加號(+)
sp 在正數前面顯示空格
# 在八進制數前面顯示零(0),在十六進制前面顯示“0x”或者“0X”(取決于用的是“x”還是“X”)
0 顯示的數字前面填充“0”而不是默認的空格
m.n m 是顯示的最小總寬度,n 是小數點后的位數(如果可用的話)
變量可以指向函數,函數的參數可以接收變量,那么函數可以接收另一個函數作為參數,這種函數稱為高階函數。
1、把函數作為實參;2、把函數作為返回值。
python高階函數有哪些?
map函數
map()是python內置的高階函數,它接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,并且把結果作為新的列表返回。
filter函數
filter()同樣也是接收一個函數和一個序列,和map()不同的是,filter函數把傳入的函數依次作用于每個元素,然后返回返回值是True的元素。
reduce函數
reduce()把一個函數作用到一個序列上,這個函數必須接收兩個參數,reduce把結果和序列的下一個元素做累積計算。
lambda函數
lambda()有時候傳參數時不需要顯示自定義的函數,直接傳入匿名函數更方便;冒號前面的X,y表示函數參數,匿名函數不需要擔心函數名的沖突,匿名函數也是一個函數對象,可以吧匿名函數賦值給一個變量,再利用變量來調用函數,匿名函數也可以作為返回值返回。
sorted函數
sorted()作為python內置高階函數之一,其功能是對序列(列表、元組、字典、集合、字符串)進行排序。
文章名稱:Python函數優先等級 python 優先級
鏈接分享:http://m.newbst.com/article32/doojgsc.html
成都網站建設公司_創新互聯,為您提供關鍵詞優化、網站建設、網站導航、動態網站、用戶體驗、定制網站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯