Python之路【第三篇補充】:Python基礎(三)


參考老師:http://www.cnblogs.com/wupeiqi

lambda表達式

學習條件運算時,對於簡單的 if else 語句,可以使用三元運算來表示,即:

# 普通條件語句
if 1 == 1:
    name = ‘luotianshuai'
else:
    name = 'shuaige'
  
# 三元運算
name = 'luotianshuai' if 1 == 1 else 'shuaige'

#這個就是if else的一個簡寫。
#if 條件成立的時候name為'luotianshuai' 不成立的時候為:'shuaige' ,語法糖!

 

那么函數有沒有他的簡寫呢?也是有的lambda表達式!

lambda 和if  else的三元運算一樣,是為了簡化函數,但是:

1、只能做簡單的操作
2、自動return

看下面兩個函數的對比:

'''正常函數'''
def func(arg):
    return arg + 1
result = func(100)
print result

'''lambda表達式'''
func2 =  lambda a: a + 1
result = func2(10000)
#這里調用函數的時候就是lambda表達式左邊的等號就是他函數的調用!
print result

#執行結果:
#101
#10001

內置函數 二

一、map

遍歷序列,對序列中每個元素進行操作,最終獲取新的序列。

解釋:

在Python中,最基本的數據結構是序列(sequence)。序列中的每個元素被分配一個序號——即元素的位置,也稱為索引。第一個索引是 0,第二個則是 1,以此類推。序列中的最后一個元素標記為 -1,倒數第二個元素為 -2,一次類推。        

Python包含 6 中內建的序列,包括列表、元組、字符串、Unicode字符串、buffer對象和xrange對象。

'''例子1'''
li =  [11,22,33]

def func1(arg):
    return arg + 1  #這里乘除都可以

new_list = map(func1,li)  #這里map調用函數,函數的規則你可以自己指定,你函數定義成什么他就做什么操作!
print new_list
輸出結果:[12, 23, 34]

'''例子2'''
li = ['shuaige','nihao',]
def func1(arg):
    return '%s test string' % arg  #或者使用+進行拼接萬惡的+能不用最好不用他會在內存中開辟新的空間!

new_strlist = map(func1,li)
print new_strlist

輸出結果:['shuaige test string', 'nihao test string']

'''例子3'''
li = 'abcdefg'
def func1(arg):
    return '%s test string' % arg

new_list = map(func1,li)
print new_list
#結果:['a test string', 'b test string', 'c test string', 'd test string', 'e test string', 'f test string', 'g test string']
map例子

 

使用lambda表達式:

li = [11,22,33,44,55]
new_li = map(lambda a:a + 100,li)
print new_li

#輸出結果:   [111, 122, 133, 144, 155]


#多個列表操作:
l1 = [11,22,33,44,55]
l2 = [22,33,44,55,66]
l3 = [33,44,55,66,77]
print map(lambda a1,a2,a3:a1+a2+a3,l1,l2,l3)
#輸出結果:  [66, 99, 132, 165, 198] 
#這里需要注意如果使用map函數列表中的元素必須是相同的才可以!否則就會報下面的錯誤!
#TypeError: unsupported operand type(s) for +: 'int' and 'NoneType',如果看下面
l1 = [11,22,33,44,55]
l2 = [22,33,44,55,66]
l3 = [33,44,55,66,]
#l3的數據少一個,如果元素里的元素為空那么他調用的時候這個元素就是None
lambda表達式

 

二、filter

對於序列中的元素進行篩選,最終獲取符合條件的序列!

li = [11,22,33,44,55,66,77,88]

print filter(lambda a:a>33,li)
輸出結果:[44, 55, 66, 77, 88]

三、reduce

對於序列內所有元素進行累計操作

li = [1,2,3,4,5,6,7,8]
result =  reduce(lambda a1,a2:a1+a2,li) #累乘、除、加、減
print result

# reduce的第一個參數,函數必須要有兩個參數,因為他是兩兩進行操作
# reduce的第二個參數,要循環的序列
# reduce的第三個參數,初始值

#初始值
li = [1,2,3,4,5,6,7,8]
result =  reduce(lambda a1,a2:a1+a2,li,100000) #累乘、除、加、減
print result

默認參數:

yield生成器

yield和return的區別:

    yield跳出函數后會記錄當前函數的狀態當下次調用的時候,從記錄的狀態開始!

    return后將直接跳出函數!

1、對比range 和 xrange 的區別

>>> print range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print xrange(10)
xrange(10)

如上代碼所示,range會在內存中創建所有指定的數字,而xrange不會立即創建,只有在迭代循環時,才去創建每個數組。

看下下面的例子:(自定義生成器)

def mrange(arg):
    seed = 0
    while True:
        seed = seed +1
        if seed > arg:
            return
        else:
            yield seed
for i in mrange(10):
    print i

 冒泡算法

 

需求:請按照從小到大對列表 [13, 22, 6, 99, 11] 進行排序

 

思路:相鄰兩個值進行比較,將較大的值放在右側,依次比較!

冒泡算法原理圖:

冒泡算法實例:
列表中有5個元素兩輛進行比較,然后用中間值進行循環替換!
既然這樣,既然這樣我們還可以用一個循環把上面的循環進行在次循環,用表達式構造出內部循環!

li = [13,22,6,99,11]
for n in range(1,len(li)):
    for m in range(len(li)-n):
        num1 = li[m]
        num2 = li[m+1]
    if num1 > num2:
        temp = li[m]
        li[m] = num2
        li[m+1] = temp
print li

讓的原理和下面一樣:

li = [13,22,6,99,11]

for m in range(4):  #等價於:for m in range(len(li)-1)
    num1 = li[m]
    num2 = li[m+1]
    if num1 > num2:
        temp = li[m]
        li[m] = num2
        li[m+1] = temp
print  li
for m in range(3): #等價於:for m in range(len(li)-2)
    num1 = li[m]
    num2 = li[m+1]
    if num1 > num2:
        temp = li[m]
        li[m] = num2
        li[m+1] = temp
print  li
for m in range(2): #等價於:for m in range(len(li)-3)
    num1 = li[m]
    num2 = li[m+1]
    if num1 > num2:
        temp = li[m]
        li[m] = num2
        li[m+1] = temp
print  li
for m in range(1): #等價於:for m in range(len(li)-4)
    num1 = li[m]
    num2 = li[m+1]
    if num1 > num2:
        temp = li[m]
        li[m] = num2
        li[m+1] = temp
print  li
冒泡算法原理

 裝飾器

裝飾器是函數,只不過該函數可以具有特殊的含義,裝飾器用來裝飾函數或類,使用裝飾器可以在函數執行前和執行后添加相應操作。

簡單的來說在不修改原函數的情況下,在對原函數進行包裝!

 

一、初創公司有N個業務部門,1個基礎平台部門,基礎平台負責提供底層的功能,如:數據庫操作、redis調用、監控API等功能。業務部門使用基礎功能時,只需調用基礎平台提供的功能即可。如下:

 

############### 基礎平台提供的功能如下 ############### 
 
def f1():
    print 'f1'
 
def f2():
    print 'f2'
 
def f3():
    print 'f3'
 
def f4():
    print 'f4'
 
############### 業務部門A 調用基礎平台提供的功能 ############### 
 
f1()
f2()
f3()
f4()
 
############### 業務部門B 調用基礎平台提供的功能 ############### 
 
f1()
f2()
f3()
f4()

 目前公司有條不紊的進行着,但是,以前基礎平台的開發人員在寫代碼時候沒有關注驗證相關的問題,即:基礎平台的提供的功能可以被任何人使用。現在需要對基礎平台的所有功能進行重構,為平台提供的所有功能添加驗證機制,即:執行功能前,先進行驗證。

老大把工作交給 Low B,他是這么做的:

 

跟每個業務部門交涉,每個業務部門自己寫代碼,調用基礎平台的功能之前先驗證。誒,這樣一來基礎平台就不需要做任何修改了。

 

 當天Low B 被開除了...

老大把工作交給 Low BB,他是這么做的:

只對基礎平台的代碼進行重構,讓N業務部門無需做任何修改
############### 基礎平台提供的功能如下 ############### 

def f1():
    # 驗證1
    # 驗證2
    # 驗證3
    print 'f1'

def f2():
    # 驗證1
    # 驗證2
    # 驗證3
    print 'f2'

def f3():
    # 驗證1
    # 驗證2
    # 驗證3
    print 'f3'

def f4():
    # 驗證1
    # 驗證2
    # 驗證3
    print 'f4'

############### 業務部門不變 ############### 
### 業務部門A 調用基礎平台提供的功能### 

f1()
f2()
f3()
f4()

### 業務部門B 調用基礎平台提供的功能 ### 

f1()
f2()
f3()
f4()
修改原基礎平台代碼

過了一周 Low BB 被開除了...

老大把工作交給 Low BBB,他是這么做的:

只對基礎平台的代碼進行重構,其他業務部門無需做任何修改
############### 基礎平台提供的功能如下 ############### 

def check_login():
    # 驗證1
    # 驗證2
    # 驗證3
    pass


def f1():
    
    check_login()

    print 'f1'

def f2():
    
    check_login()

    print 'f2'

def f3():
    
    check_login()

    print 'f3'

def f4():
    
    check_login()
    
    print 'f4'
新建立一個函數把函數應用到原基礎函數上

老大看了下Low BBB 的實現,嘴角漏出了一絲的欣慰的笑,語重心長的跟Low BBB聊了個天:

老大說:

寫代碼要遵循開發封閉原則,雖然在這個原則是用的面向對象開發,但是也適用於函數式編程,簡單來說,它規定已經實現的功能代碼不允許被修改,但可以被擴展,即:

  • 封閉:已實現的功能代碼塊
  • 開放:對擴展開發

如果將開放封閉原則應用在上述需求中,那么就不允許在函數 f1 、f2、f3、f4的內部進行修改代碼,老板就給了Low BBB一個實現方案:

def w1(func):
    def inner():
        # 驗證1
        # 驗證2
        # 驗證3
        return func()
    return inner
 
@w1
def f1():
    print 'f1'
@w1
def f2():
    print 'f2'
@w1
def f3():
    print 'f3'
@w1
def f4():
    print 'f4'

 

對於上述代碼,也是僅僅對基礎平台的代碼進行修改,就可以實現在其他人調用函數 f1 f2 f3 f4 之前都進行【驗證】操作,並且其他業務部門無需做任何操作。

Low BBB心驚膽戰的問了下,這段代碼的內部執行原理是什么呢?

老大正要生氣,突然Low BBB的手機掉到地上,恰恰屏保就是Low BBB的女友照片,老大一看一緊一抖,喜笑顏開,交定了Low BBB這個朋友。詳細的開始講解了:

單獨以f1為例:

def w1(func):
    def inner():
        print 'gongneng1'
        func()
        print 'gongneng2'
    return inner

@w1
def f1():
    print 'f1'

f1()

 當執行的時候,python是由上到下執行的,首先執行到def w1(func):這里把def w1(func)加載到內存

當執行到@w1的時候@w1是python的語法糖!他會把他下面的函數進行封裝。

把f1這個函數作為def w1(func)的參數傳進去!就是:f1()=w1(f1)

然后def w1(func):  == w1(f1)就會執行:

    def inner():
        print 'gongneng1'
        func()   #func()  == f1()“原函數”
        print 'gongneng2'
    return inner  #然后把封裝后的函數輸出給原函數

@w1就相當於做了一個替換

def f1()  <==> def inner()

@w1
def f1():         #  ==def inner() :
    print 'f1'    #           print 'gongneng1'
                  #           func()
                  #           print 'gongneng2'

 

二、被裝飾的函數如果有參數呢?

def w1(func):
    def inner(arg):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(arg)
    return inner

@w1
def f1(arg):
    print 'f1'

一個參數


################################
def w1(func):
    def inner(arg1,arg2):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(arg1,arg2)
    return inner

@w1
def f1(arg1,arg2):
    print 'f1'

兩個參數
################################
def w1(func):
    def inner(arg1,arg2,arg3):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(arg1,arg2,arg3)
    return inner

@w1
def f1(arg1,arg2,arg3):
    print 'f1'

三個參數

 用動態參數搞定!

def w1(func):
    def inner(*args,**kwargs):
        # 驗證1
        # 驗證2
        # 驗證3
        return func(*args,**kwargs)
    return inner
 
@w1
def f1(arg1,arg2,arg3):
    print 'f1'

三、一個函數可以被多個裝飾器裝飾嗎?

def w1(func):
    def inner(*args,**kwargs):
        print 'gongneng1'
        func(*args,**kwargs)
        print 'gongneng2'
    return inner
def w2(func):
    def inner(*args,**kwargs):
        print 'gongneng3'
        func(*args,**kwargs)
        print 'gongneng4'
    return inner

@w1
@w2
def f1(arg,arg2,arg3):
    print arg,arg2,arg3

f1('nihao','tianshuai','shuaige')

 輸出結果:

gongneng1
gongneng3
nihao tianshuai shuaige
gongneng4
gongneng2

 這個被多個裝飾器裝飾,其實就是套完一層在套一層!勿把自己繞進去!

 四、還有什么更吊的裝飾器嗎?

def Filter(a1,a2):
    def outer(main_func):
        def wrapper(request,kargs):
            print a1
            main_result = main_func(request,kargs)
            print a2
                return main_result
        return wrapper
    return outer

@Filter(f5, f6)
def Index(request,kargs):
    print 'index'
    
'''
1、第一步:把def Filter(a1,a2): 加載到內存
2、第二步:@Filter(f5, f6)  == 調用了裝飾器  == @outer 然后返回給函數
3、第散步:執行outer函數並返回給index函數  Index == wrapper
4、執行wrapper 函數,這樣做的意義就是除了原函數給的參數外,裝飾器也可以調用自己定義的參數

'''

 這樣做的意義就是除了原函數給的參數外,裝飾器也可以調用自己定義的參數


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM