1.把函数作为对象
Python函数就是对象,下面以一个例子简要介绍一下。其中,map函数返回的是一个可以迭代的对象,里面的元素是把第一个参数(一个函数)作用到第二个参数(一个可以迭代的对象)中各个元素上得到的结果。
def factorial(n):
"""return n!"""
return 1 if n<2 else n*factorial(n-1)
a = factorial(42)
b = map(factorial, range(11))
print(a, b)
print(factorial.__doc__)
print(type(factorial))
2.高阶函数
接受函数作为参数,或者把函数作为结果返回的函数是高阶函数。像sorted函数就是,任何单参数函数都可以作为key参数的值。但有些高阶函数,在新的Python版本中有了更好的替代。如:map和filter函数可以用之前说到的生成器表达式来替代,用reduce函数求和,现在可用sum函数来进行替代。reduce和sum函数的通用思想都是把某个操作连续应用到序列的元素上,累计之前的结果,把一系列值归约成一个值。
类似的,all和any内置函数也是归约函数。all(iterable)中iterable参数中的每一个值都是真值才返回True,any(iterable)中iterable参数中有一个值是真值,就返回Ture。
3.匿名函数
lambda关键字在Python表达式内构建匿名函数。lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。先简要介绍一下lambda表达式。
lambda [arg1 [ ,arg2,.. . ..argn]]:expression
在lambda表达式中,冒号前的参数可以是一个也可以是多个,冒号后的表达式只有一个。该函数是将冒号前的参数带入到冒号后的表达式中,并返回相应的值。下面的例子中,用lambda表达式构建了一个求和函数。这里要注意的是lambda表达式创建的是一个函数对象。
#求和函数
sum1 = lambda x, y: x+y
print(sum1(1,2))
#使用lambda表达式反转拼写,然后依次排序
fruits = ['apple', 'banana', 'fig', 'pear']
a = sorted(fruits, key=lambda word : word[::-1])
print(a)
4.可调用对象以及用户定义的可调用的类型
在Python中,调用运算符(即())除了可以用在函数上,还可以用在其他对象上,一般我们用内置的callable()函数查看一个对象可不可以被调用。差不多有7中可以调用的对象。
用户定义的函数 | 用def语句和lambda表达式创建 |
内置函数 | 使用C语言创建的函数,如:len |
内置方法 | 使用C语言实现的方法,如:dict.get |
方法 | 在类的定义体中定义的函数 |
类 | 使用Class创建 |
类的实例 | 如果类定义了_call_方法,它的实例就可调用 |
生成器函数 | 使用yeild关键字生成的函数和方法 |
5.函数内省
除了_doc_,函数对象还有许多属性。使用dir函数可以得知某个函数所具有的属性。
print(dir(sorted))
6.从定位参数到仅限关键字参数
Python3中进一步提供了仅限关键字参数,与之密切相关的是,调用函数时使用*和**“展开”可迭代对象,映射到单个参数。
def tag(name, *content, cls=None, **attrs):
"""生成一个或多个HTML标签"""
if cls is not None:
attrs['class'] = cls
if content:
return '\n'.join('<%s>%s' % (name, c, name) for c in content)
第一个参数后面的人一个参数会被*content捕获,存入一个元组。tag函数中没有明确指定名称的关键字参数会被**attrs捕获,存入一个字典当中。
7.函数注释
Python中提供了一种句法,用于为函数声明中参数和返回值附加元数据。
def clip(text: str, max_len: 'int>80') -> str:
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()
函数声明中的各参数可以在:之后添加注解表达式。如果参数有默认值的话,注解放在参数名和等号之间。如果想注解返回值,在)和函数声明的末尾之间添加->和一个表达式。上面的例子中,text是一个字符串,max_len最大为80个整型,最后->str表示返回值为字符串。
此外,Python .rfind() 返回字符串最后一次出现的位置(从右向左查询),如果没有匹配项则返回-1。
str.rfind(str, beg=0, end=len(string))
参数:str -- 查找的字符串,beg -- 开始查找的位置,默认为 0,end -- 结束查找位置,默认为字符串的长度。
8.支持函数式编程的包
8.1operator模块
在函数式编程当中,经常需要把算术运算符当做函数使用。我们经常会用到的是reduce函数。下面给一个简单的例子。
from functools import reduce
from operator import mul
def fact(n):
return reduce(mul, range(1, n+1))
print(fact(4))
reduce() 函数会对参数序列中元素进行累积,然后返回累积得到的结果。
reduce(function, iterable[, initializer])
其中,function -- 函数,还有两个参数,iterable -- 可迭代对象,initializer -- 可选,初始参数。
此外,该模块中还有itemgetter函数,最常见的用途即:根据元组的某个字段给元组进行排序。attrgetter函数,它创建的函数会根据名称提取对象的属性。并返回提取值构成的元组。
8.2使用functools.partial冻结参数
functools.partial这个高阶函数用于部分应用的一个函数。基于一个函数创建一个新的可调用的对象,把原函数的某些参数固定。
from functools import partial
from operator import mul
triple = partial(mul, 3)
print(triple(7))
上述例子中,将一个需要两参数的函数转换成单参数,即固定了一个相乘的参数为3。