热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:python一等函数

篇首语:本文由编程笔记#小编为大家整理,主要介绍了python一等函数相关的知识,希望对你有一定的参考价值。把函数视作对象

篇首语:本文由编程笔记#小编为大家整理,主要介绍了python一等函数相关的知识,希望对你有一定的参考价值。


把函数视作对象

在 Python 中,函数是一等对象。编程语言理论家把“一等对象”定义为满足下述条件的程序实体:



  • 在运行时创建



  • 能赋值给变量或数据结构中的元素



  • 能作为参数传给函数



  • 能作为函数的返回结果

说明python 函数是对象:这里创建了一个函数,然后调用它,读取它的 __doc__ 属性,并且确定函数对象本身是 function 类的实例。


def factorial(n):
‘‘‘returns n!‘‘‘
return 1 if n <2 else n * factorial(n - 1)
print(factorial(5)) #调用
print(help(factorial)) #打印__doc__属性
print(type(factorial)) #打印类型
#结果
120
Help on function factorial
in module __main__:
factorial(n)
returns n!
#__doc__属性
None
<class function> #说明factorial是function类的一个实例

说明函数是一等对象:通过别名使用函数(对应于第二点),把函数作为参数传递(对应于第三点)。


#创建一个函数,只有函数在调用的时候才会运行
def factorial(n):
‘‘‘returns n!‘‘‘
return 1 if n <2 else n * factorial(n-1)
fact
= factorial
print(fact)
map_fact
= map(factorial, range(11))
print(map fact:, map_fact)
print(list(map_fact))
#结果

map fact:

[
1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]

高阶函数

接受函数为参数,或者把函数作为结果返回的函数是高阶函数。

如map,filter,reduce,sorted。

map(function, iterable, ...) 会根据提供的函数对指定序列做。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

filter(function, iterable接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

reduce(function, iterable[, initializer])函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果

sorted(iterable[, cmp[, key[, reverse]]])   排序函数

sorted示例,reverse函数作为参数,逆置的单词排序。


>>> def reverse(word):
...
return word[::-1]
...
>>> reverse(testing)
gnitset
>>> reverse(fruits)
[
banana, raspberry, cherry, apple, fig, strawberry]
>>> fruits
[
strawberry, fig, apple, cherry, raspberry, banana]
>>> sorted(fruits, key=reverse)    #reverse作为sorted函数的参数
[banana, apple, fig, raspberry, strawberry, cherry]

map和filter示例,计算阶乘:


>>>def factorial(n):
return 1 if n <2 else n * factorial(n - 1)
>>>list(map(factorial,range(6))) #0到5的阶乘
[1, 1, 2, 6, 24, 120]
list(map(factorial,filter(
lambda n: n % 2,range(6)))) #过滤掉偶数的阶乘
[1, 6, 120]

reduce示例,求和:


from functools import reduce #reduce在functools模块下
from operator import add
reduce(add,range(
100))
4950
sum(range(
100))
4950

sum和reduce思想是把某个操作连续应用到序列的元素上,累计之前的结果,把一系列值规约成一个值。类似的函数还有any和all.

all(iterable)   //如果iterable的每个元素都是真值,返回True,否则返回False

any(iterable)    //只要有iterable的某个元素是真值就返回True。

匿名函数 

lambda函数定义体中不能赋值,也不能使用while和try等python语句。适合用在参数列表中。(lambda表达式会创建函数对象


fruits = [banana, raspberry, cherry, apple, fig, strawberry]
sorted(fruits, key
=lambda word: word[::-1]) #逆置的单词排序,代替了sorted示例中的reverse函数
[banana, apple, fig, raspberry, strawberry, cherry]

可调用对象和可调用类型

可以使用()符号调用的对象即为可调用对象

如下:

用户定义的函数:def语句或lambda函数创建

内置函数:C语言实现的函数,如len或time.strftime

内置方法:C语言实现的方法,如dict.get

方法:类中定义的函数

类:调用类时会调用__new__方法创建一个实例,然后运行__init__方法初始化实例返回调用方。

类实例:如果类定义了__call方法,那么它的实例可以作为函数调用。

生成器函数:使用yield关键字的函数或方法。

可以使用callable()函数判断对象是否可以调用


>>>[callable(obj) for obj in (abs,str,13)]
[True, True, False]

用户定义的可调用类型

任何python对象都可以表现得像函数,只要实现__call__方法


import random
class BingoCage:
def __init__(self, items):
self._items
= list(items)
random.shuffle(self._items)
#打乱顺序
def pick(self):
try:
return self._items.pop()
except IndexError:
raise LookupError(pick from empty BingoCage)
def __call__(self, *args, **kwargs): #实现__call__方法
return self.pick()
bingo
= BingoCage(range(3))
print(bingo.pick())
print(bingo()) #调用bingo
print(callable(bingo)) #判断是否可调用
#结果:
0
2
True

函数内省

函数对象不止有__doc__属性,还有很多其他属性,可用dir()函数查看


>>>dir(factorial)
[
__annotations__, __call__, __class__, __closure__, __code__, __defaults__, __delattr__, __dict__, __dir__, __doc__, __eq__, __format__, __ge__, __get__, __getattribute__, __globals__, __gt__, __hash__, __init__, __kwdefaults__, __le__, __lt__, __module__, __name__, __ne__, __new__, __qualname__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__]

 

用户定义的函数的属性




























































名称类型说明
__annotations__dict参数返回值和的注释信息
__call__method-wrapper实现()运算符;即可调用对象协议
__closure__tuple函数闭包,即自有变量的绑定(通常是None)
__code__code编译成字节码的函数元数据和函数定义体
__defaults__tuple形式参数的默认值
__get__method-wrapper实现只读描述符协议
__globals__dict函数所在模块中的全局变量
__kwdefaults__dict仅限关键字形式参数的默认值
__name__str函数名称
__qualname__str函数的限定名称,如Random.choice

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 获取函数参数信息(法一)

函数的__default__属性保存着定位参数和关键字参数的默认值

函数的__code__包含许多参数信息,如:

__code__.co_argcount包含参数个数 

__code__.co_varnames包含参数名称   (值得注意的是,这里包含函数体内定义的局部变量,真正的参数名称是前N个字符串,N的个数由co__argcount确定;且其中不包含前缀为*和**的变长参数)


def clip(text, max_len=20):
"""在max_len前面或后面的第一个空格处截断文本
"""
end
= None
if len(text) > max_len:
space_before
= text.rfind( , 0, max_len)
if space_before >= 0:
end
= space_before
else:
space_after
= text.rfind( , max_len)
if space_after >=0:
end
= space_after
if end is None:
end
= len(text)
return text[:end].rstrip()
print(clip.__defaults__) #从后往前扫描,故max_len的默认值为20
print(clip.__code__)
print(clip.__code__.co_argcount) #包含局部变量
print(clip.__code__.co_varnames) #如结果,实际参数为2

(
20,)
"C:/py_code/nov06/Schimidt.py", line 1>
2
(
text, max_len, end, space_before, space_after)

获取函数参数信息(法二)

使用inspect模块下的signature()函数,signature()函数返回一个signature对象,它有一个parameters属性,这是一个有序映射,把参数名和inspecr.Parameter对象对应起来。各个Parameter有各自属性:name(名称),default(默认值),kind(类型)   //特殊的inspect._empty代表没有默认值


from inspect import signature
sig
= signature(clip) #clip为上个示例的函数,参数元组
print(sig)
print(str(sig))
for name, param in sig.parameters.items():
print(param.kind, :, name, =, param.default)
#打印 参数类型:参数名称:参数默认值

#结果
(text, max_len
=20)
(text, max_len
=20)
POSITIONAL_OR_KEYWORD : text
= <class inspect._empty>
POSITIONAL_OR_KEYWORD : max_len
= 20

kind属性值是_ParameterKind类的5个值之一,如下:

 






























POSITIONAL_OR_KEYWORD可以通过定位参数和关键字参数传入的形参,多数python参数类型属于此类 
VAR_POSITIONAL定位参数元组*   参数
VAR_KEYWORD关键字参数字典**  参数
KEYWORD_ONLY仅限关键字参数 
POSITONAL_ONLY仅限定位参数 

 

 

 

 

 

  

 

 

 

 

 函数注解

除了name,kind,default,inspect.Parameter对象还有一个annotation(注解)属性,它的值通常为inspect._empty,但可能包含注解句法提供的函数签名元素据。

函数声明中的各个参数可以在:之后增加注解表达式。如果参数有默认值,注解放在参数名和 = 号之间。如果想注解返回值,在 )和函数声明末尾的:之间添加->和一个表达式,那个表达式可以是任意类型。

为clip函数添加注解:


def clip(text, max_len:int > 0=20) -> str: #max_len参数注解和返回值注解
"""在max_len前面或后面的第一个空格处截断文本
"""
end
= None
if len(text) > max_len:
space_before
= text.rfind( , 0, max_len)
if space_before >= 0:
end
= space_before
else:
space_after
= text.rfind( , max_len)
if space_after >=0:
end
= space_after
if end is None:
end
= len(text)
return text[:end].rstrip()
print(clip.__annotations__)
#结果
{max_len: int > 0, return: <class str>}

Python 对注解所做的唯一的事情是,把它们存储在函数的__annotations__ 属性里。仅此而已,Python 不做检查、不做强制、不做验证,什么操作都不做。换句话说,注解对 Python 解释器没有任何意义。注解只是元数据,可以供 IDE、框架和装饰器等工具使用。标准库中还没有什么会用到这些元数据,唯有inspect.signature() 函数知道怎么提取注解,如示例所示:


sig = signature(clip)
print(sig.return_annotation)
for param in sig.parameters.values():
note
= repr(param.annotation).ljust(13) #param.annotation获取注解,rerp返回注解的string形式
print(note, :, param.name, ‘‘, param.default)
<class str>
<class inspect._empty> : text <class inspect._empty>
int > 0 : max_len 20

支持函数式编程的包

operator模块为多个算术运算符提供了对应的函数,例如可以使用mul来代替使用匿名函数lambda a,b:a * b

operator还有itemgetterattrgetter函数。

itemgetter常见用途:根据元组的某个字段给元组列表排序。(itemgetter[i]类似lambda fields:fields[1],创建一个接受集合的函数,返回索引位1上的元素)


from operator import itemgetter
metro_data
= [
(
tokyo, JP, 36),
(
mexico, IN, 21),
(
new york, US, 20),
(
sao paulo, BR, 19),
]
for city in sorted(metro_data, key=itemgetter(1)): #按照元组第二项排序
print(city)
#结果
(sao paulo, BR, 19)
(
mexico, IN, 21)
(
tokyo, JP, 36)
(
new york, US, 20)
for city in sorted(metro_data, key=itemgetter(2)): #按照元组第三项排序
print(city)
#结果
(sao paulo, BR, 19)
(
new york, US, 20)
(
mexico, IN, 21)
(
tokyo, JP, 36)

多个参数传递给itemgetter,它构建的函数会返回提取的值构成的元组


cc_name = itemgetter(1, 0)
for city in metro_data:
print(cc_name(city))

#结果
(JP, tokyo)
(
IN, mexico)
(
US, new york)
(
BR, sao paulo)

functools.partial冻结参数

functols.partial用于部分应用于一个函数。即:基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。使用这个函数可以把接受一个或多个参数的函数改编成需要回调的API,这样需要的参数更少。


from operator import mul #乘法
from functools import partial
triple
= partial(mul, 3) #把第一个参数固定为3
print(triple(7))
print(list(map(triple, range(1, 10))))
21
[
3, 6, 9, 12, 15, 18, 21, 24, 27]

functools.partialmethod函数作业于partial一样,不过是用于处理方法。

以上来自《流畅的python》第五章



推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
author-avatar
葫芦娃才是萌神
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有