我是靠谱客的博主 故意心锁,最近开发中收集的这篇文章主要介绍python进阶学习(三)函数被视作对象的函数高阶函数匿名函数函数式编程相关模块可调用类型处理参数函数注解,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 被视作对象的函数
  • 高阶函数
  • 匿名函数
  • 函数式编程相关模块
  • 可调用类型
  • 处理参数
    • 捕获不定参数
    • 仅限关键字参数
  • 函数注解


被视作对象的函数

在python中函数是一等对象,“一等对象”的定义是满足下述条件的程序实体:

  • 在运行时创建
  • 能赋值给变量或数据结构中的元素
  • 能作为参数传给函数
  • 能作为函数的的返回结果

python中的函数完全符合上面的条件,如果打印函数的类型会发现,python的函数都是function类的实例

def sum(a,b):
    return a+b

print(type(sum)) # <class 'function'>

fact = sum
print(fact(1,4)) # 5

高阶函数

接受函数为参数或者把函数作为结果返回的函数就是高阶函数(higher-order function)

内置的sorted函数就是高阶函数,其中有个参数key接受的就是函数

import random

lis = [random.randint(-10,10) for x in range(10)]

sorted(lis, key=abs)

上面的sorted将绝对值函数abs作为参数进行比较判断

在函数式编程中比较常见的有filter,map,reduce,apply,在python中有*和**符号处理不定参数,所有apply并不需要,而filter和map很多时候可以用列表推导式来代替。

filter和英文名一样,作用是过滤,将不符合条件的排除,filter第一个参数是高阶函数,第二个是要处理的序列,filter和map返回的都是生成器。

import random

lis = [random.randint(-10,10) for x in range(10)] # 随机生成一个10个数字的列表

# 判断是否大于0
def gt_zero(x):
    return True if x>0 else False

list(filter(gt_zero, lis)) 结果可以是[6,4,2]

map表示映射,直白来说就是一对一的映射,对序列中每个元素都做相同的操作后,得到一个新的序列

import random

lis = [random.randint(-10,10) for x in range(10)] # 随机生成一个10个数字的列表

# 计算三次方函数
def cubed(x):
    return x**3

list(map(cubed, lis)) # 结果可以是[-64, 64, 64, 27, -729, 343, 1, -343, 1000, 0]

reduce,规约,通过某个操作应用到序列的元素上,它会累计之前的计算结果,把一些列值规约为一个值,相当于多对一映射

import random
from functools import reduce

lis = [random.randint(-10,10) for x in range(10)]

# 累乘
def mul(x,y):
    return x*y

reduce(mul, lis)

注意,这个reduce并不是内置函数,要从functools导入才行

匿名函数

lambda关键字可以创建匿名函数,顾名思义,就是没有名字的函数,在一些需要用到简单函数,并且该函数并不需要复用时,可以使用lambda来构造函数。

不够python的匿名函数中只能使用纯表达式,不能赋值,也不能用while和try等语句。

上面的例子都可以用lambda表示构建同样语义的函数

import random
from functools import reduce

lis = [random.randint(-10,10) for x in range(10)]

reduce(lambda x,y: x*y, lis)
list(map(lambda x: x**3, lis))

使用lambda时,先写上关键字lambda,写上参数,使用逗号分隔,写上":"符号,:后面代表的是返回值,例如lambda x,y,z: x+y+z,代表三数求和

lambda其实和def语句一样,也会创建函数对象,就是没有名字。

函数式编程相关模块

首先,python不是函数式,不过利用functools和operator这两个模块,可以方便地编写出函数式风格的python代码

python自带了sum函数可以自动求和,不过没有自动求乘积的函数,所以上面我们利用匿名函数自己写了这么一个功能

reduce(lambda x,y: x*y, lis)

而operator模块中就带有这类算术运算符函数,避免了我们使用这种平凡的匿名函数,例如:

from operator import mul
reduce(mul, lis) # 与上面代码同义

除了算术运算符外,operator还有用来从序列中读取元素的对象,例如itemgetter和attrgetter

itemgetter代表从一个序列中读出第i个元素值,itemgetter(2)就相当于lambda x: x[2]

而attrgetter代表从一个映射中读出某个键值的元素,attrgetter(‘key’)就相当于lambda x: x[‘key’]

可调用类型

某个对象是否是可调用的,可以用python内置函数callable()来判断。

list(map(callable, [int, abs, 12]))
[True, True, False]

只要类实现了__call__方法,那么它就可以像函数一样被调用

下面的类实现了一个累加器,每次调用MyClass的实例,都会将数值累加到count上,并且返回count值,我们看到使用callable判断MyClass的实例,结果也是该实例为可调用对象。

list(map(callable, [int, abs, 12]))

class MyClass():
    
    def __init__(self):
        self.count = 0
        
    def __call__(self, new_value):
        if isinstance(new_value, int):
            self.count = self.count + new_value
        return self.count

a = MyClass()

callable(a) # Ture
a(12) # 12
a(32) # 44
a(8) # 52

像类似于上面在类内部维护count值,让对象在多次调用中都可以使用到保存的count值,我们也可以使用闭包的概念来实现,不过闭包不在这里描述。

处理参数

捕获不定参数

在python使用*和**可以捕获不确定个数的参数

*content代表除了前面的a,之后传入的非关键字参数都会被*content捕获,并且存入一个元组

**attrs代表,之后传入的带有关键字(当然这个关键字没有在之前参数中被明确指定)的参数都会被**attrs捕获,并且存入一个字典

def fun(a, *content, **attrs):
    print(content)
    print(attrs)
    
fun(123,1,2,3,4,5,6,7,8,9,key=10)
# (1, 2, 3, 4, 5, 6, 7, 8, 9)
# {'key': 10}

仅限关键字参数

利用上面的机制,因为*只会捕获非关键字参数,所以把一定要使用关键字传入的参数放到*的后面,且不使用**来捕获参数

def fun(a, *, b):
    return (a,b)

# fun(1,2) 这样会报错,因为在这种写法下,b只能使用带关键字的参数
fun(1, b=2)

函数注解

函数注解用于给函数声明中的参数以及返回值附加元数据。

注解本身不会做任何的处理,(当然你要是利用注解功能,自己写了点代码用于类型检查或者额外功能,这种另算),只会在函数的__annotations__属性中存储下来。

想想吧,你写完了一个函数,又想规范地将参数或者返回值的额外信息记录下来,这时候你就额外写了张便签条,记录下信息,贴在了这个函数上,附带的信息就这么保存下来了,你可以随时调用__annotations__来看看写了点啥。

def substr(text:str, start:'int >= 0'=0)->str:
    return reverse[start::-1]

print(substr.__annotations__)
{'text': <class 'str'>, 'start': 'int >= 0,and', 'return': <class 'str'>}

在参数之后,使用:之后写上注解,如果参数有默认值,那么就在参数名和=之间放上注解,如果要在返回值上增加注解,那么在)与:之间写上->符号,并写上注解。

注解可以是任何类型,不过最常用的是类型(如str,int),或者一个字符串(‘int >= 0’)


上一篇:python进阶学习(二)数据结构–字典和集合
下一篇:python进阶学习(四)装饰器与闭包

最后

以上就是故意心锁为你收集整理的python进阶学习(三)函数被视作对象的函数高阶函数匿名函数函数式编程相关模块可调用类型处理参数函数注解的全部内容,希望文章能够帮你解决python进阶学习(三)函数被视作对象的函数高阶函数匿名函数函数式编程相关模块可调用类型处理参数函数注解所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部