1. 程式人生 > >python進階知識點

python進階知識點

1.Python支援的函數語言程式設計

A.不是純函數語言程式設計:允許有變數(純函數語言程式設計:不需要變數,沒有副作用,測試簡單

B.支援高階函式:函式可以作為變數傳入

C.支援閉包:有了閉包就能返回函式

D.有限度地支援匿名函式

2.高階函式

能接收函式做引數的函式

變數可以指向函式

函式的引數可以接受變數

一個函式可以接收另一個函式作為引數

能接收函式作引數的函式就是高階函式

A.map()python內建的高階函式,它接收一個函式f和一個list,並通過把函式f依次作用在list的每個元素上,得到一個新的list並返回

B.reduce()函式也是

python內建的一個高階函式,reduce()函式接收的引數和map()類似,一個函式f,一個list,但行為和map()不同,reduce()傳入的函式f必須接收兩個引數,reduce()list的每個元素反覆呼叫函式f,並返回最終結果值,reduce()還可以接收第三個可選引數,作為計算的初始值.

C.filter()函式式python內建的另一個有用的高階函式,filter()函式接收一個函式f和一個list,這個函式f的作用是對每個元素進行判斷,返回True或者False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新的list

請利用filter()過濾出

1~100中平方根是整數的數,即結果應該是:

import math
def is_sqr(x):
    return math.sqrt(x)%1 == 0
print filter(is_sqr, range(1, 101))

D.sorted()函式可對list進行排序,同樣也是一個高階函式,它可以接收一個比較函式來實現自定義排序

對內容進行忽略大小寫排序

def campstr(s1,s2):
    return cmp(s1.lower(),s2.lower())
print sorted(['bob', 'about', 'Zoo', 'Credit'],campstr)

3.閉包

Python的函式不但可以返回int,str,list,dict等資料型別,還可以返回函式

Python中閉包,在函式內部定義的函式和外部定義的函式式一樣的,只是無法被外部訪問,如果有被定義在外函式內部的情況,並且內層函式引用了外層函式的引數,然後返回內層函式的情況,我們稱為閉包.

閉包的特點是返回的函式還引用了外層函式的區域性變數,所以要正確地使用閉包,就要確保引用的區域性變數在函式返回後不能變.

Python中的匿名函式,高階函式可以接收函式做引數,有些時候,我們不需要顯式地定義函式,直接傳入匿名函式更方便,python,對匿名函式提供了有限支援,關鍵字lambda表示寧明函式,冒號前面的x表示函式引數  eg: lambda x:x*x  匿名函式有一個限制,就是隻能有一個表示式,不寫return,返回值就是該表示式的結果

 

4.裝飾器

Python內建的@語法就是為了簡化裝飾器呼叫

@new_fn
def f1(x):
Return x*2  
 
def f1(x):
return x*2
f1 = new_fn(f1)

作用:

可以極大地簡化程式碼,避免每個函式編寫重複性程式碼

列印日誌:@log

檢測效能:@performance

資料庫事務:@transaction

URL路由:@post(‘/register’)

請編寫一個@performance,它可以打印出函式呼叫的時間。

import time
def performance(f):
    def fn(x):
        time1 = time.time()
        val = f(x)
        print "run time = ",time.time() - time1
        return val
    return fn
 
@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
 
print factorial(10)
 

5.偏函式

當一個函式有很多引數的時候,呼叫者就需要提供多個引數,如果減少引數個數,就可以簡化呼叫者的負擔

我們在sorted這個高階函式中傳入自定義排序函式就可以實現忽略大小寫排序。請用functools.partial把這個複雜呼叫變成一個簡單的函式:sorted_ignore_case(iterable)

def campstr(s1,s2):
    return cmp(s1.lower(),s2.lower())
sorted_ignore_case = functools.partial(sorted,cmp= campstr)
print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit'])

6.模組和包的概念

當代碼越來越多的時候如果將所有的程式碼放入一個py檔案:無法維護

如果將程式碼分拆放入多個py檔案中,好處:

同一個名字的變數互不影響

引用其他的模組

#test.py ---> 自身模組名

Import math --->引用math模組

 

當模組多了以後,也容易重名,解決模組名衝突,只要將模組放入到不同的包中就可以解決

引用完整的模組名:

Import p1.util  

使用:

P1.util.demo()

 

包就是資料夾,模組名就是.py

如何區分包和普通目錄:

包下面有個_init_.py這樣python才會當做包來處理

 

動態匯入模組

如果匯入的模組不存在,python直譯器會報ImportError錯誤

EG:

利用import ... as ...,還可以動態匯入不同名稱的模組。

Python 2.6/2.7提供了json 模組,但Python 2.5以及更早版本沒有json模組,不過可以安裝一個simplejson模組,這兩個模組提供的函式簽名和功能都一模一樣。

試寫出匯入json 模組的程式碼,能在Python 2.5/2.6/2.7都正常執行。

try:
    import json
except ImportError:
    import simplejson as json
 
print json.dumps({'python':2.7})

使用__future__

Python的新版本會引入新的功能,但是,實際上這些功能在上一個老版本中就已經存在了,要試用某一新的特性,就可以通過匯入__future__模組的某些功能來實現

例如:

from __future__ import division
print 10 / 3   #3.3333333333333335
print 10//3   #3

安裝第三方模組

a.easy_install

b.pip(推薦,已內建到Python2.7.9)

例如安裝web.py第三方模組

pip install web.py

7.Python面向物件程式設計

面向物件程式設計是一種程式設計正規化

把程式看做不同物件的相互呼叫

對現實世界建立物件模型

基本思想

類用於定義抽象型別

例項根據類的定義被創建出來

最重要的思想:資料封裝

由於Python是動態語言,對每一個例項,都可以直接給他們的屬性賦值

可以給一個例項繫結很多屬性,如果不希望被外部訪問到,可以用__雙下劃線開頭,該屬性就無法被外部訪問.但是如果一個屬性以 __xxx__的形式定義,則又可以被外部訪問了,__xxx__定義的屬性在python的類中被稱為特殊屬性,有很多預定義的特殊屬性可以使用,通常不把普通屬性用__xxx__定義

8.類屬性

繫結在例項上的屬性不會影響其他例項,但是,類本身也是一個物件,如果在類上繫結一個屬性,則所有例項都可以訪問類的屬性,並且,所有例項訪問的類屬性都是同一個,也就是說,例項屬性每個例項各自擁有,互相獨立,而類屬性有且只有一份(類似於javastatic)

定義類屬性可以直接在class中定義

class Demo(object):
data1 = 12
Print Demo.data1

因為類屬性是直接繫結在類上的,所以訪問類屬性不需要建立例項.

對一個例項呼叫類的屬性也是可以訪問的,所有例項都可以訪問到它所屬的類的屬性

由於Python是動態語言,類屬性也是可以動態新增和修改的...

當例項屬性和類屬性重名時,例項屬性優先順序高,它將遮蔽掉對類屬性的訪問。不要在例項上修改類屬性,它實際上並沒有修改類屬性,而是給例項綁定了一個例項屬性

9.例項方法

例項的方法就是在類中定義的函式,它的第一個引數永遠是 self,指向呼叫該方法的例項本身,其他引數和一個普通函式是完全一樣的:在例項方法內部,可以訪問所有例項屬性,這樣,如果外部需要訪問私有屬性,可以通過方法呼叫獲得,這種資料封裝的形式除了能保護內部資料一致性外,還可以簡化外部呼叫的難度。

class中定義的例項方法其實也是屬性,實際上是一個函式物件,因為方法也是一個屬性,所以它也可以動態地新增到例項上,只是需要用type.MethodType()把一個函式變為一個方法

10.類方法

和屬性類似,方法也分例項方法和類方法.class中定義的全部是例項方法,例項方法第一個引數self是例項本身.通過標記@classmethod 該方法將繫結到類上,而非類的例項上,該方法的第一個引數將傳入類本身,通常將引數名命名為cls,因為是在類上呼叫,而非例項上呼叫,因此類方法無法獲取任何例項變數,只能獲得類的引用

class Person(object):
    count = 0
    @classmethod
    def how_many(cls):
        return cls.count

11.類的繼承

子類和父類是is關係,總是從某各類繼承 如果沒有合適的就從object繼承,不能忘記呼叫super().__init__

如果已經定義了Person類,需要定義新的StudentTeacher類時,可以直接從Person類繼承:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

定義Student類時,只需要把額外的屬性加上,例如score

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score

一定要用 super(Student, self).__init__(name, gender) 去初始化父類,否則,繼承自 Person  Student 將沒有 name  gender

函式super(Student, self)將返回當前類繼承的父類,即 Person ,然後呼叫__init__()方法,注意self引數已在super()中傳入,在__init__()中將隱式傳遞,不需要寫出(也不能寫)。

12.判斷型別

函式isinstance()可以判斷一個變數的型別,既可以用在Python內建的資料型別如str,list,dict,也可以用在我們自定義的類,它們本質上都是資料型別

Isinstance(“ss”,str)

繼承鏈上,一個父類的例項不能是子類型別,因為子類比父類多了一些屬性和方法,一個例項可以看成它本身的型別,也可以看成它父類的型別。

13.多型

類具有繼承關係,並且子類型別可以向上轉型看做父類型別,因此在例項方法的繼承以及複寫而言和java類似,但是bug的是因為python是動態語言,因此python在呼叫例項方法的時候不檢查型別,只要方法存在,引數正確即可以呼叫.意思是:只要類中有這個方法,那麼類似於這樣的方法定義:

def demo(x):
x.demomethod()

只要x中有demomethod這個方法就可成功的呼叫demo方法.

14.多重繼承

除了從一個父類繼承外,python允許從多個父類繼承,稱為多繼承

class A(object):
def __init__(self):
pass
def hi(self):
print "A hi"
pass
class B(object):
def __init__(self):
pass
def hi(self):
print "B hi"
pass
class C(A,B):
def __init__(self):
pass
 
c = C()
c.hi()

15.獲取物件資訊

拿到一個變數,除了用isinstance()判斷是否是某種型別的例項外,可以用type()函式獲取變數的型別,返回一個Type物件,也可以用dir()函式獲取變數的所有屬性,getattr()獲取屬性值,setattr()設定屬性值


16.特殊方法



用於print__str__

用於len__len__

用於cmp__cmp__

 

特殊方法的特點

a.定義在class

b.不需要直接呼叫

c.某些函式或者操作符會呼叫對應的特殊方法

 

 

正確實現特殊方法

A.只需要編寫用到的特殊方法

B.有關聯性的特殊方法都必須實現

__getattr__

__setattr__

__delattr__

C.__str____repr__

如果要把一個類的例項變成str,需要實現特殊方法__str__()

__repr__()用於顯示給開發人員看

D.__cmp__

int,str等內建資料型別排序時,pythonsorted()按照預設比較函式cmp排序,但是,如果對一組例項排序的時候,就必須提供自己的特殊方法__cmp__,__cmp__用例項自身self和傳入的例項 s 進行比較,如果 self 應該排在前面,就返回 -1,如果 s 應該排在前面,就返回1,如果兩者相當,返回 0

E.__len__

如果一個類表現的像list,要獲取有多少個元素,就得用len()函式,要讓len()函式工作正常,類就必須提供一個特殊方法__len__()

F.數學運算

Python提供的基本資料型別int,float可以做整數和浮點的四則運算以及乘方等運算,但是四則運算不侷限於intfloat,還可以是有理數,矩陣等,要表示有理數,可以用Rational類來表示

G.型別轉換

對於資料的型別轉換 如下:

int(12.23)    ---- > 12
float(12)   	-----> 12.0

如果要把一個物件轉換為int應該實現特殊的方法__int__()

然後呼叫 int(obj) 即可

Float同理類似

 

[email protected]

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.__score = score
    @property
    def score(self):
        return self.__score
    @score.setter
    def score(self, score):
        if score < 0 or score > 100:
            raise ValueError('invalid score')
        self.__score = score

如上 可以通過對getter方法進行@progperty註解 ,這樣就會將score()衍生出score屬性,在呼叫的時候 可以通過 s.scoreget或者set

I.__slots__

如果要限制新增的屬性,例如,Student類只允許新增 namegenderscore 3個屬性,就可以利用Python的一個特殊的__slots__來實現。

顧名思義,__slots__是指一個類允許的屬性列表:

class Student(object):
    __slots__ = ('name', 'gender', 'score')
    def __init__(self, name, gender, score):
        self.name = name
        self.gender = gender
        self.score = score


現在,對例項進行操作:

>>> s = Student('Bob', 'male', 59)

>>> s.name = 'Tim' # OK

>>> s.score = 99 # OK

>>> s.grade = 'A'

Traceback (most recent call last):

  ...

AttributeError: 'Student' object has no attribute 'grade'

__slots__的目的是限制當前類所能擁有的屬性,如果不需要新增任意動態的屬性,使用__slots__也能節省記憶體。

J.__call__

一個類例項也可以變成一個可呼叫物件,只需要實現一個特殊方法__call__()

我們把 Person 類變成一個可呼叫物件:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
 
    def __call__(self, friend):
        print 'My name is %s...' % self.name
        print 'My friend is %s...' % friend

現在可以對 Person 例項直接呼叫:

>>> p = Person('Bob', 'male')

>>> p('Tim')

My name is Bob...

My friend is Tim...

單看 p('Tim') 你無法確定 p 是一個函式還是一個類例項,所以,在Python中,函式也是物件,物件和函式的區別並不顯著。