python函数的高级话题

本文介绍了Python中的函数式编程高级特性,包括lambda表达式、map函数、filter函数、reduce函数的使用,以及Iterator和Generator的概念与应用。通过示例展示了这些特性如何简化代码和提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信了解python的朋友对python的函数肯定不会陌生,一个def定义一个函数,这是最常用的也是最基本的,但除此之外python在函数式编程方面还提供了什么高级特性呢


  • 匿名函数lambda
    语法:lambda 函数参数一,参数二……:表达式 -> 函数变量
    lambda这个词大家肯定很熟悉吧,现在很多语言像java,lua都开始支持lambda表达式了,而python中的lambda表达式并不与它们相同,python中的lambda常用在匿名函数上,是一种生成函数对象的表达式形式,像def一样它创建一个能被调用的函数,但是他返回一个函数而不是把这个函数赋给一个变量名,更不需要一个变量名去引用这个函数,当然你也可以这么做,这也就是称之为匿名函数的原因,什么意思呢,举个例子来看一下:
python
def func(x,y,z):
    return x + y + z
if __name__=='__main__':
    func(0,1,2)

在上面这个超简单的例子里,我们定义了一个函数,它的名字叫做func,我们用的时候就是和很多语言的函数调用方式一样:函数名(参数),那实际上我们为什么可以这么调用呢,其实是这样的,当python执行def语句时,会根据编译好的字节码和命名空间等信息创建一个函数对象,而函数名就相当于是这个函数类的一个对象,(有没有觉得和java每个对象所属的类都是Class这个类的一个对象很像呢,所以说语言的很多思想和设计都是相通的),即函数名相当于是一个引用变量,引用着所定义的函数所属的这个对象,每次调用这个函数时就相当于使用这个对象的方法,再来看lambda表达式:

python
if __name__=='__main__':
    func = lambda x,y,z:x+y+z
    func(1,2,3)

如果你之前没有接触过匿名函数,也许你会一声惊叹,尼玛这也行!嗯,在python中这样确实是行的而且在一些特定的场合下还是很有用处的,什么场合下呢,比如这些:
- 函数功能用表达式就能完成(这个必须满足,因为lambda中只能有表达式不能有语句)
- 某些函数非常短小而且仅会在某个位置使用
- 你想取的函数名已经被定义,避免与其他变量名冲突
- 回调,尤其在GUI的事件触发中用的最多
- ……
往后看它与其他内置函数式编程的结合,你会发现lambda是如此的简洁,并且当你真正理解了之后代码的可读性也是不错的

  • map
    语法:map(function,sequence) ->list
    这个map不是指的数据结构的map映射,而是一个函数,他以sequence中的每个元素作为参数执行函数function,并将结果放在一个list中返回给调用者,显而易见的一个好处就是省代码!!!这和python的简洁的理念是完全符合的,我们程序员当然也更喜欢少敲点无脑的代码,下面再来看一个例子:
python
counters = [1,2,3,4]
updated = []
for x in couters:
     updated.append(x+10)

再来看看用map怎么写:

python

def inc(x):
    return x+10
counters = [1,2,3,4]
map(inc,couters)

貌似也不是很简洁啊,咱们再看一个常用的例子:

python
import urllib2
urls=["url1","url2"]
results = []
for url in urls:
    conn = urllib2.open(url)
    results.append(conn)

用map呢:

python
import urllib2
urls = ["url1","url2"]
results = map(urllib2.urlopen,urls)

呵呵,是不是惊呆了呢~~~
再来看看map和,lambda的合体:

python
map(lambda x:x+10,[1,2,3,4])

怎么样,还不错吧,清晰简洁(当然在你能理解map和lambda的情况下),除了简洁之外其实map函数还有一个优势就是速度,基本上是普通for循环的2倍,尤其是在执行内置函数的时候,不过python本身在速度上并不占优势,这个优点就有点弱化了。但仅凭简洁这一点就有足够的理由让我们去使用它了,不过千万不要滥用,嵌套太深会让代码的可读性大大降低,那可就得不偿失了

  • filter
    语法:filter(function,sequence) ->list
    从名字上就可以看出来,这是一个过滤的函数,用法类似于map加上了if条件的筛选,筛选条件由function来定义,比较简单,再来个例子大家肯定就懂了:
python
>>>filter(lambda x:x>0,range(-5,5))
[1,2,3,4]

很简单,从后面的序列中选择符合前面函数定义条件的值,即使得函数返回True的值组成一个list返回,在这个例子中就是从[-5,4]中的整数中选择>0的值

  • reduce
    语法:reduce(function,sequence) ->list
    这个稍微复杂一点,以sequence的第一个值为初始值依次向后进行function的操作,并将计算的结果继续和后面的值就行function操作,直至最后一个元素,有点抽象,来看个例子:
python
>>>reduce((lambda x,y:x+y),[1,2,3,4])
10

等价于

python
def add(x,y):
    return x + y
sum = 0;
for i in [1,2,3,4]:
    sum += i

这下就该懂了吧,是一个迭代的过程,不过不太理解为什么要取reduce这个名字,有知道的朋友请告知,thx

  • Iterator 和Generator
    其实这是为下面的列表解析这条做准备的,像c++,java这些语言中都有Iterator也就是迭代器的概念,说白了就是每次调用迭代器的某个方法时,迭代器会返回一个值,然后下次调用时在返回上次返回值的下一个,如此迭代知道最后,那现在我们来具体看看python的Iterator是怎么回事:
python
>>>mylist = [1,2]
>>>myiter = iter(mylist)
>>>myiter.next()
 1
>>>myiter.next()
 2
>>>myiter.next()
 Traceback (most recent call last):
  File "<stdin>", line 1, in ?
    it.next()
 StopIteration

上面演示了一个简单的迭代器使用的例子,相信大家也看到了python中的迭代器是怎么工作的:首先用用iter方法得到一个可迭代对象的迭代器iterator,然后逐步调用迭代器的next方法,这样每次回返回一个值,知道最后抛出StopIteration异常标志访问结束,当然实际使用时一般我们不用直接这么写,比如用for循环时就会自动地为我们执行这些方法,并且捕获最后抛出的StopIteration异常:

python
>>>mylist = [1,2]
>>>for(ele in mylist):
...     print ele;
1
2

那么我们如何自定义一个可迭代的对象呢,也很简单,只要这个对象实现了__iter__方法并且返回一个实现了next方法来返回值的对象就可以了:

python
class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def next(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]

也是挺简单的吧,不过这里产生的迭代器和一般的不太一样,它是按照逆序返回的,只要写好next方法就能让迭代器按你所需逐步返回元素,ok这就是python中的迭代器Iterator
再说一下Generator生成器,生成器更方便了我们的使用,他能产生一个迭代器,并且也会在使用过程中自动执行它的next方法:

python
>>>def reverse(data):
...     for index in range(len(data)-1, -1, -1):
...        yield data[index]
>>>for char in reverse('go'):
...     print char
o
g

在上面的reverse函数中,使用yield返回数据,这样其实是返回了一个生成器,然后每次调用这个方法时就会用自动调用生成器的next方法并且在最后自动抛出Iteration异常,这样就使得使用时的代码更加紧凑,更符合python简洁的风格
ok,有了迭代器和生成器的概念,咱们再来看看列表解析


  • 列表解析
    语法:[表达式:for循环 (可选的if语句用于筛选元素)]
    列表解析就更常用了,其实上面几个函数的功能用列表解析都可以实现,很多情况下速度也更快,还是举个例子看看吧:
python
>>>[x**2 for x in range(-5,5) if x>0]
1,4,9,16

for循环的执行过程大家应该都比较清楚了吧,for ele in sequence:code 首先计算sequence并调用其__iter__函数得到sequence的生成器generator,然后逐步执行generator的next函数取得sequence的相应元素赋值给ele,然后进行相关操作,如此迭代直至抛出异常StopIteartion,而列表解析就是在for循环的基础上增加了对元素进行函数操作和返回列表,当然也可以自定义条件来选择sequence的元素(这样就实现了fliter的效果),可以说列表解析更加简洁易读,速度也更胜一筹,充分运用它一定能让我们的代码更pythonic


先来这些吧,后续再补充

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值