一等函数
一等函数满足:
- 在运行时创建
- 能赋值给变量或数据结构中的元素
- 能作为参数传给函数
- 能作为函数的返回结果
把函数视作对象,并通过参数传递:
def factorial(n): if n<2: return 1 else: return n*factorial(n-1) fact = factorial print('factorial:',type(factorial)) print(list(map(fact,range(11))))
输出:
factorial: <class 'function'>
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
一些高阶函数:
# filter根据传入函数返回值为True还是False进行过滤,过滤掉False的 # 返回一个生成器 print('filter with lambda:',list(filter(lambda n: n % 2 != 0, range(6)))) def odd(x): return x % 2 != 0 print('filter with odd:',list(filter(odd,range(6)))) # reduce根据传入函数对可迭代对象的所有元素进行运算 # 返回一个生成器 from functools import reduce def add(x,y): return x + y print('reduce with add:',reduce(add, range(101))) # 如果每个元素都是真,all返回True,all([])返回True l = [True,True,True] print('all with [True,True,True]:',all(l)) l = [True,True,False] print('all with [True,True,False]:',all(l)) l = [] print('all with []:',all(l)) # 只要iterable中有元素为真,any就返回True,any([])返回False l = [False,False,False] print('any with [False,False,False]:',any(l)) l = [True,False,False] print('any with [True,False,False]:',any(l)) l = [] print('any with []:',any(l))
输出:
filter with lambda: [1, 3, 5]
filter with odd: [1, 3, 5]
reduce with add: 5050
all with [True,True,True]: True
all with [True,True,False]: False
all with []: True
any with [False,False,False]: False
any with [True,False,False]: True
any with []: False
用户定义的可调用类型
- 任何Python对象都可以表现得像函数。为此,只需实现实例方法__call__
- 判断一个对象是否可调用,使用内置callable()函数
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): return self.pick() bingoCage = BingoCage(list(range(10))) print('is bingoCage callable:',callable(bingoCage)) for i in range(10): print(bingoCage(),end=' ')
输出:
is bingoCage callable: True
2 9 0 8 4 1 6 5 3 7
函数的参数
- 参数分类
- 定位参数:调用时通过位置匹配实参
- 关键字参数:调用时通过位置或参数名称匹配实参
- 仅限关键字参数:调用时只能通过参数名称匹配实参
- 未命名的定位参数:匹配多个连续的定位参数,将他们放进一个元组,形如 *args
- 未命名的关键字参数:匹配多个连续的仅限关键字参数,将他们放进一个dict,形如 **kwargs
- 参数顺序
- 定位参数、关键字参数、未命名的定位参数(或者只写一个*号用于占位),仅限关键字参数、未命名的关键字参数
def say_hello(pos1, pos2=2, *args, kw_only=3, **kwargs): print('定位参数和关键字参数:pos1 = %s,pos2 = %s' % (pos1, pos2)) print('未命名的定位参数:args = ', args) print('仅限关键字参数:kw_only = ', kw_only) print('未命名的关键字参数:kwargs = ', kwargs) say_hello(0,1,2,3,4,5,kw_only=6,name='zhangsan',age=7)
输出:
定位参数和关键字参数:pos1 = 0,pos2 = 1
未命名的定位参数:args = (2, 3, 4, 5)
仅限关键字参数:kw_only = 6
未命名的关键字参数:kwargs = {'name': 'zhangsan', 'age': 7}
获取关于参数的信息
def say_hello(pos1, pos2=2, *args, kw_only=3, **kwargs): inner = 1 print('定位参数和关键字参数:pos1 = %s,pos2 = %s' % (pos1, pos2)) print('未命名的定位参数:args = ', args) print('仅限关键字参数:kw_only = ', kw_only) print('未命名的关键字参数:kwargs = ', kwargs) # __defaults__包括关键字参数的默认值 print(say_hello.__defaults__) print('-' * 100) # __kwdefaults__包括仅限关键字参数的默认值 print(say_hello.__kwdefaults__) print('-' * 100) # co_name就是函数名 print(say_hello.__code__.co_name) print('-' * 100) # co_varnames包括了形参和内部变量 print(say_hello.__code__.co_varnames)
输出:
(2,)
----------------------------------------------------------------------------------------------------
{'kw_only': 3}
----------------------------------------------------------------------------------------------------
say_hello
----------------------------------------------------------------------------------------------------
('pos1', 'pos2', 'kw_only', 'args', 'kwargs', 'inner')
函数注解
- 在函数声明中为参数和返回值附加元数据
- 注解可以是类或者字符串
- python只把注解存储在函数的__annotations__属性里,什么其他操作都不做
def say_hello(pos1: str,pos2: 'pos2') -> str: pass print(say_hello.__annotations__)
输出:
{'pos1': <class 'str'>, 'pos2': 'pos2', 'return': <class 'str'>}