1.把对象当函数调用
如果类定义了 __call__ 方法,那么它的实例可以作为函数来调用。
如果想判断对象能否调用,可以使用内置的 callable() 函数。
[callable(obj) for obj in (abs, str, 13)] [True, True, False] #abs是函数,str是类,都可调用
除了 __doc__,函数对象还有很多属性。使用 dir 函数可以探知属性。
2.函数注解
为函数参数和返回值声明类型.
def clip(text:str, max_len:'int > 0'=80) -> str: pass
Python 对注解所做的唯一的事情是,把它们存储在函数的 __annotations__ 属性里。仅此而已,Python 不做检查、不做强制、不做验证,什么操作都不做。
换句话说,注解对Python 解释器没有任何意义。注解只是元数据,可以供 IDE、框架和装饰器等工具的静态类型检查功能提供类型信息。
写作本书时,标准库中还没有什么会用到这些元数据,唯有 inspect.signature() 函数知道怎么提取注解
3.operator模块
itemgetter 和 attrgetter 其实会自行构建函数。
itemgetter 的常见用途:根据元组的某个字段给元组列表排序。
from operator import itemgetter 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)) ] for city in sorted(metro_data, key=itemgetter(1)): #根据第2个字段排序 print(city)
把多个参数传给 itemgetter,它构建的函数会返回提取的值构成的元组
cc_name = itemgetter(1, 0) for city in metro_data: print(cc_name(city))
attrgetter 创建的函数根据名称提取对象的属性
methodcaller 创建的函数会在对象上调用参数指定的方法
from operator import methodcaller s = 'The time has come' upcase = methodcaller('upper') upcase(s) #'THE TIME HAS COME' hiphenate = methodcaller('replace', ' ', '-') hiphenate(s) #'The-time-has-come'
4.functools模块
1.functools.cmp_to_key(func)的使用:
def cmp1(n1, n2): return n1 - n2 a = [1, 6, 2, 9] print(sorted(a, key=functools.cmp_to_key(cmp1)))
2.@functools.lru_cache(maxsize=128, typed=False)用于装饰器,它会存储耗时的函数调用结果,避免重新计算。
被 lru_cache 装饰的函数会有 cache_clear 和 cache_info 两个方法,分别用于清除缓存和查看缓存信息。
from functools import lru_cache @lru_cache(maxsize=32) def fib(n): print('calling the fib function....') if n < 2: return n return fib(n-1) + fib(n-2) if __name__ == '__main__': print(list([fib(n) for n in range(16)])) [print(func) for func in dir(fib) if not func.startswith('_')] print(fib.cache_info())
3.functools.partial(func[,*args][, **keywords])偏函数,用于固定参数
import functools def add(a,b): return a + b add3 = functools.partial(add,3) print add3(4)
4.functools.reduce(function, iterable[, initializer])
from functools import reduce ret=reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) # 计算的就是((((1+2)+3)+4)+5) print(ret) # 15
5.@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
from functools import wraps def my_decorator(f): @wraps(f) def wrapper(*args, **kwds): print('Calling decorated function') return f(*args, **kwds) return wrapper