函数

高阶函数

map、 filter

>>> list(map(fact, range(6))) ➊
[1, 1, 2, 6, 24, 120]
>>> [fact(n) for n in range(6)] ➋
[1, 1, 2, 6, 24, 120]
>>> list(map(factorial, filter(lambda n: n % 2, range(6)))) ➌
[1, 6, 120]
>>> [factorial(n) for n in range(6) if n % 2] ➍
[1, 6, 120]
>>>

并不推荐使用map以及filter函数,而是用列表推导式.

reduce

>>> from functools import reduce ➊
>>> from operator import add ➋
>>> reduce(add, range(100)) ➌
4950
>>> sum(range(100)) ➍
4950
>>>

等是针对mul,这个还是比较方便的.

all(iterable)

如果 iterable 的每个元素都是真值,返回 True; all([]) 返回 True。

for c in words:
    if c not in it:
        break
        
# 改写为
all(c in it for c in words)

any(iterable)

只要 iterable 中有元素是真值,就返回 True; any([]) 返回 False。

可调用对象

如果想判断对象能否调用,可以使用内置的 callable() 函数。
只需实现实例方法 __call__

用户定义的函数的属性

名称 类型 说明
__annotations__ dict 参数和返回值的注解
__call__ methodwrapper 实现 () 运算符;即可调用对象协议
__closure__ tuple 函数闭包,即自由变量的绑定(通常是 None)
__code__ code 编译成字节码的函数元数据和函数定义体
__defaults__ tuple 形式参数的默认值
__get__ methodwrapper 实现只读描述符协议(参见第 20 章)
__globals__ dict 函数所在模块中的全局变量
__kwdefaults__ dict 仅限关键字形式参数的默认值
__name__ str 函数名称
__qualname__ str 函数的限定名称,如 Random.choice(参阅PEP 3155,https://www.python.org/dev/peps/pep-3155/)

从定位参数到仅限关键字参数

def f(a, *, flag=False, **, ):
    pass

为什么不写成def(a, flag=False),这是怕误传参数.

支持函数式编程的包

operator模块

  • 使用 reduce 函数和一个匿名函数计算阶乘
from functools import reduce
def fact(n):
    return reduce(lambda a, b: a*b, range(1, n+1))
  • 使用 reduce 和 operator.mul 函数计算阶乘
from functools import reduce
from operator import mul
def fact(n):
    return reduce(mul, range(1, n+1))
  • attrgetter 与 itemgetter 作用类似,它创建的函数根据名称提取对象的属性。如果把多个属性名传给 attrgetter,它也会返回提取的值构成的元组。此外,如果参数名中包含 .(号), attrgetter 会深入嵌套对象,获取指定的属性。
>>> 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)),
... ]
>>>
>>> from operator import itemgetter
>>> for city in sorted(metro_data, key=itemgetter(1)):
...              print(city)
...
('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833))
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889))
('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
('Mexico City', 'MX', 20.142, (19.433333, -99.133333))
('New York-Newark', 'US', 20.104, (40.808611, -74.020386))

>>> cc_name = itemgetter(1, 0)
>>> for city in metro_data:
...         print(cc_name(city))
...
('JP', 'Tokyo')
('IN', 'Delhi NCR')
('MX', 'Mexico City')
('US', 'New York-Newark')
('BR', 'Sao Paulo')
>>>
>>> from collections import namedtuple
>>> LatLong = namedtuple('LatLong', 'lat long') # ➊
>>> Metropolis = namedtuple('Metropolis', 'name cc pop coord') # ➋
>>> metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long)) # ➌
...                for name, cc, pop, (lat, long) in metro_data]
>>> metro_areas[0]
Metropolis(name='Tokyo', cc='JP', pop=36.933, coord=LatLong(lat=35.689722, long=139.691667))
>>> metro_areas[0].coord.lat # ➍
35.689722
>>> from operator import attrgetter
>>> name_lat = attrgetter('name', 'coord.lat') # ➎
>>>
>>> for city in sorted(metro_areas, key=attrgetter('coord.lat')): # ➏
...             print(name_lat(city)) # ➐
...
('Sao Paulo', -23.547778)
('Mexico City', 19.433333)
('Delhi NCR', 28.613889)
('Tokyo', 35.689722)
('New York-Newark', 40.808611)
  • 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

使用functools.partial冻结参数

数创建一个新的可调用对象,把原函数的某些参数固定。使用这个函数可以把接受一个或多个参数的函数改编成需要回调的 API,这样参数更少。

  • 使用 partial 把一个两参数函数改编成需要单参数的可调用对象
>>> from operator import mul
>>> from functools import partial
>>> triple = partial(mul, 3) ➊
>>> triple(7) ➋
21
>>> list(map(triple, range(1, 10))) ➌
[3, 6, 9, 12, 15, 18, 21, 24, 27]
  • 使用 partial 构建一个便利的 Unicode 规范化函数
>>> import unicodedata, functools
>>> nfc = functools.partial(unicodedata.normalize, 'NFC')
>>> s1 = 'café'
>>> s2 = 'cafe\u0301'
>>> s1, s2
('café', 'café')
>>> s1 == s2
False
>>> nfc(s1) == nfc(s2)
True

partialmethod

"""
    >>> cell = Cell()
    >>> cell.alive
    False
    >>> cell.set_alive()
    >>> cell.alive
    True

"""
from functools import partialmethod


class Cell(object):
    def __init__(self):
        self._alive = False

    @property
    def alive(self):
        return self._alive

    def set_state(self, state):
        self._alive = bool(state)

    set_alive = partialmethod(set_state, True)
    set_dead = partialmethod(set_state, False)
posted @ 2018-02-12 11:55  Yuanoung  阅读(277)  评论(0)    收藏  举报