导语:本文章记录了本人在学习Python基础之函数篇的重点知识及我的心得,打算入门Python的朋友们能够来一块儿学习并交流。
本文重点:html
一、了解函数在Python中是一等对象;
二、了解Python中的可调用对象;
三、掌握正肯定义函数参数的方法;
四、了解operator和functools中支持函数式编程的方法。
定义:一等对象是知足以下条件的程序实体:python
在Python中,全部函数都是一等对象。
程序员
定义:接受函数为参数,或者把函数做为结果返回的函数是高阶函数。
在Python中传统的高阶函数有map,filter,reduce;经常使用的高阶函数有内置函数sorted、min、max和functools.partial。正则表达式
定义:可以接受一个可迭代对象并返回单个结果的函数是归约函数。
reduce就是归约函数的一种,sum也是一种归约函数。本章额外介绍两个内置的归约函数。express
all(iterable):
可迭代对象中每个元素都是真值则返回True,不然False。
any(iterable)
可迭代对象中存在一个元素是真值则返回True,不然False。
归约函数会在第14章中讨论可迭代对象时重点讲解。编程
匿名函数:使用lambda表达式建立的函数,函数自己没有名字来辨识,于是叫作匿名函数。
句法特色:lambda函数只能使用纯表达式,不能赋值,也不能使用while和try等语句。
语法:lambda [arg1 [,arg2,.....argn]]:expression。
优势:建立方便,简化代码工做量。
缺点:代码可读性下降。数组
在计算机编程中,自省是指这种能力:检查某些事物以肯定它是什么、它知道什么以及它能作什么。自省向程序员提供了极大的灵活性和控制力。性能优化
在函数的定义过程可能须要传入参数,对于函数涉及到的参数分为如下四种:数据结构
参数组合:当函数涉及到使用多种参数时,定义和传入的参数需按照的顺序:必填参数、默认参数、可变参数、强制关键字参数、关键字参数.
并发
def func(name,country="China",*,age,**rest): print("name :",name," country :",country," age :",age," rest :",rest) func("Jack","US",age=20) func("Hoya",age=15,male="Boy",height="178",grade="excellent",country="UK") #output: name : Jack country : US age : 20 rest : {} name : Hoya country : UK age : 15 rest : {'male': 'Boy', 'height': '178', 'grade': 'excellent'}
#强制关键字参数错误传参 func("Hoya",country="UK",20) SyntaxError: positional argument follows keyword argument #强制关键字参数只能利用关键字传入参数
注:函数参数知识引自
做者:东皇Amrzs
能够经过A=inspect.signature(object)提取关于函数参数的信息;
signature支持signature.parameter方法返回关于参数的有序映射。
signature支持signature.bind(args, *kwargs)方法,此方法可将多个实参绑定到签名的形参来接受。
注解(annotation)从Python3开始存在,用于为函数声明中的参数和返回值附加元数据。只有inspect.signature()能够提取注解。
本人目前把注解简单理解为一种标签。
定义:支持调用运算符()的对象叫作可调用对象。
判断方法:利用内置的callable()函数判断。
Python数据模型包含7种可调用对象:
下面针对类的实例为示范进行调用操做:
class Text: def __init__(self,text): self.text=str(text) def number_search(self): import re num_search=re.compile(r"\d+") return print("number search :",num_search.findall(self.text)) def __call__(self, *args, **kwargs): return self.number_search() a=Text("asdljlj55fsa56af6af66f598as5asf6af59nf3asf830fa3s") a.number_search() #输出: number search : ['55', '56', '6', '66', '598', '5', '6', '59', '3', '830', '3']
从中能够看出,建立函数类对象的简便方式是实现__call__方法。
相比较命令式编程,函数式编程是经过函数来保存程序的状态的。或者更准确一点,它是经过函数建立新的参数或返回值来保存程序的状态的。
认识函数式编程应掌握的两个本质:
注:函数式编程知识引自
做者:Jan Fan
Python的目标不是变成函数式编程语言,但经过operator和functools等包也能够进行函数式编程,下面开始介绍这两个模块。
本节介绍operator中的mul、itemgetter、attrgetter、methodcaller四种方法。
import operator from _functools import reduce #计算阶乘 def fact1(): list1=filter(lambda x: x%2,range(8)) return reduce(operator.mul,list1) print(fact1())#输出:105
metro_data =[('Tokyo', 'JP', 36.933, (35.689722, 139.691667)), ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)), ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)), ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)), ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833))] a=itemgetter(1,0) for i in metro_data: print(a(i))#注意分清楚a和i谁是参数,被处理的可迭代对象是参数。 #输出: ('JP', 'Tokyo') ('IN', 'Delhi NCR') ('MX', 'Mexico City') ('US', 'New York-Newark') ('BR', 'Sao Paulo')
eg:按照城市经度顺序输出城市名和城市经度
from collections import namedtuple from _operator import attrgetter latlong=namedtuple("latlong","lat long") citydata=namedtuple("citydata", "city ID pop coord") city=[citydata(city,ID,pop,latlong(lat,long)) for city, ID,pop,(lat,long) in metro_data] #拆包+列表推导。拆包注意city,ID,pop,latlong(lat,long)和citydata具名元组的结构对应关系,至于拆包用的变量名字是什么并不重要,保证可读性便可。 b=attrgetter("city","coord.lat") #方法1 for i in sorted(city,key=attrgetter("coord.lat")): print(b(i)) #方法2 for i in sorted(city,key=lambda x: x[3][0]): print(b(i)) #输出 ('Sao Paulo', -23.547778) ('Mexico City', 19.433333) ('Delhi NCR', 28.613889) ('Tokyo', 35.689722) ('New York-Newark', 40.808611)
from operator import methodcaller c=methodcaller("upper") d=methodcaller("islower") print(c("apple"),d("apple")) #输出 APPLE True.
语法:functools.partial(func, *args, **keywords)
functools.partial适用于函数冻结参数的状况。冻结参数是指咱们欲调用的函数中的部分或所有参数已经固定,只需补齐剩下的参数调用便可。能够按照word编辑中的格式刷来理解。
from functools import partial from unicodedata import normalize clean=partial(normalize,"NFC")#字符串格式化,我以为很像格式刷啊。 e="café" f="cafe\u0301" print(e==f) #False print(clean(e)==clean(f))#True
使用技巧总结:operator中的itemgetter、attrgetter和functools.partial在使用上都须要先构建相似正则表达式的compile partern,即构建对应的itemgetter,attrgetter和partial,而后在partern基础上传入待处理对象。
以刚才的partial举例就是clean(e),而不是e(clean)。