1. 程式人生 > >Python3學習(16)--匿名函式lambda

Python3學習(16)--匿名函式lambda

我們前面講高階函式的時候,已經很多次的提到了lambda,它是一個表示式,也是Python中的匿名函式,我們知道,lambda可以當做函式來使用,返回值就是lambda表示式的結果,lambda也可以當做函式的返回值,比如我們講到的素數求解,其中有個函式就是這樣寫的:

我們使用lambda表示式的目的不是為了能替代函式,而是儘可能的替代一些簡單的函式,注意是簡單的。

插播一個修改Wing自動程式碼補全鍵值的方法:

 修改方法:edit  -> preferences -> Editor -> Auto-completion

 把右邊keys的地方,從tab改成enter




我們看個對比,前面也講過,是一帶而過的那種,下面我們再細緻一點:

其實就是一個表示式,返回值就是表示式的結果,理解和用起來不是太難,唯一可講的地方,就是和一些函式的結合使用,它充當著小弟的角色,哪裡需要就出現在哪裡。

我們現在知道Python的 lambda表示式,非常簡潔,那其他語言呢?下面呢,我們就通過一個例子,來對比一下C#和Python的lambda表示式:

例子:

大環境           :有一個學生類,類裡面有三個成員變數,姓名,性別和年齡

新增學生物件 :我們分別建立三個學生物件,並用集合list儲存

我們要做的    :篩選這個list集合,我們只要年齡小於18歲的學生

A、C#

Lambda表示式

"Lambda表示式"是一個匿名函式,是一種高效的類似於函數語言程式設計的表示式,Lambda簡化了開發中需要編寫的程式碼量。它可以包含表示式和語句

格式:例如x => x * x,=> 讀作 goes to, 整個式子的意思就是 x 最終等於 x * x 的結果< --> x goes to x*x

我們看我們的demo實現:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    public class Student {
        private string Sname;//學生姓名

        private string Ssex ;//性別
        private int    Sage ;//年齡

        public Student(string name,string sex,int age)
        {
            this.Sname = name;
            this.Ssex  = sex ;
            this.Sage  = age ;
        }
        public string Sex
        {
            get { return Ssex; }
            set { Ssex = value; }
        }
        public string Name
        {
            get { return Sname; }
            set { Sname = value; }
        }
        public int Age
        {
            get { return Sage; }
            set { Sage = value; }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Student s1 = new Student("張三","男",22);
            Student s2 = new Student("李婷","女",15);
            Student s3 = new Student("李四","男",17);

            List<Student> list = new List<Student>();
            list.Add(s1);
            list.Add(s2);
            list.Add(s3);

            IEnumerable<Student> results = list.Where(Student => Student.Age < 18);
            Console.WriteLine("篩選出年齡小於18歲的學生集合:");
            foreach(Student s in results)
            {
                Console.WriteLine("姓名: "+s.Name+",性別: "+s.Sex+",年齡: "+s.Age.ToString());
            }
        }
    }


resuls是一個可迭代的物件集合,在Python中,我們可以通過for迴圈進行遍歷,也可以用iter()函式獲得迭代器,通過next進行逐一遍歷,在C#中,我們就用foreach,依次取出results裡面的 Student物件,然後對物件進行資訊列印,我們也發現,上述的lambda表示式,是作用在list上的,這點和Pyhon是不是一樣,我們在Python中見到lambda表示式的地方也都是作用在一個可以迭代的物件上的,比如map、filter、sorted等函式,我們發現C#的lambda表示式好像沒有Python的簡潔,雖然實現的功能一樣,因為C#是強型別,而Python是弱型別,因此,你會發現,Python中替我們省去了很多demo,不說了,我們看下C#的實現:

結果就不用解釋了,下面我們來觀望一下Python,同樣的思路,同樣的構造類和成員變數,同樣使用lambda表示式,返回同樣的結果,我們的Python是怎麼做的:

B、Python

demo如下:

#/usr/bin/env Python3
#-*- encoding:UTF-8 -*-
class Student(object):  #定義一個學生類,該類繼承自object
    def __init__(self, name, sex,age): #Python的成員變數屬性一體化
        self.name = name
        self.sex  = sex
        self.age  = age
 
#我們建立三個學生物件      
s1 = Student("張三","男",22)
s2 = Student("李婷","女",15)
s3 = Student("李四","男",17)

#我們用list存放這三個物件
L = []
L.append(s1)
L.append(s2)
L.append(s3)

#我們通過lambda表示式(匿名函式)用filter過濾掉年齡小於18歲的學生集合
#過濾後得到一個新的的迭代器,我們list轉換一下再次交付給L
L = list(filter(lambda s:s.age<18,L))

print('篩選出年齡小於18歲的學生集合:')

#注意,下面我們對L進行遍歷,s其實是一個Student物件,因此,訪問name這裡不能利用索引s[0],No! 
#正確的訪問類中的成員變數應該 --> 物件.成員變數 --> s.name
for s in L:
    print("姓名: ",s.name,",性別: ",s.sex+",年齡: ",s.age)

關於Python面向物件部分,我們後續會講到;

我們整體看Python的程式碼實現,我們發現,咋一看,我們有點蒙,不是因為它有多麼的複雜,反而是因為,它太簡潔了,簡潔的我們都不敢相信這樣的demo也可以實現我們的功能,程式碼量可是比C#的少將近一半。尤其是過濾的部分,我們的Python內建了過濾函式filter,因此我們可以很輕鬆的結合lambda表示式重新產生一個迭代器Iterator,對於C#來說,還需要另外定義一個列舉器來存放lambda表示式的結果,再對比類,顯然Python的更加出色,但是比較抽象,好在,我們寫程式碼的時候,可以省不少事。

我們看下Python的執行結果:

通過本篇的學習,我們對lambda算是比較熟悉了吧,確實很好用,但是我們也別太"依賴"它,為什麼這樣說呢,比如你要實現一個複雜的函式,你想到了我們學過的lambda,而你又不知道這個函式用lambda該怎麼寫,於是你就在那折騰,折騰老半天最終發現,還是寫不出來,那請記住,不是所有的函式都能用lambda表示式來代替,它是有侷限性的,如果你能寫出來lambda,就寫,寫不出來,就用函式吧,別問我為什麼,因為我也寫不出來。

結束語:

學無止境啊,學的越多,接觸的越多,反而覺得自己不會的也太多,敢說自己在某一方面精通的人,要麼是吹出來的,要麼就是真本事,我欽佩後者。

“會當凌絕頂,一覽眾山小”  -- 送給正在學習路上的我們,以此勉勵。