3

《流畅的Python》----第五章 一等函数

 1 year ago
source link: https://tfeima.github.io/2018/12/06/%E7%AC%AC%E4%BA%94%E7%AB%A0%20%E4%B8%80%E7%AD%89%E5%87%BD%E6%95%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[toc]

第五章 一等函数

函数是一等对象,一等对象需满足

  • 在运行时创建
  • 能赋值给对象或者数据结构中的元素
  • 能作为参数传递给函数
  • 能作为函数的返回结果

在Python中,整数、字符串、字典等都是一等对象,函数也是一等对象,只是把函数视作一等对象的时候,简称为一等函数。

把函数视作对象

函数也是对象,本身是function类的实例

接受函数作为参数,或者把函数作为返回结果的函数叫做高阶函数。常见的高阶函数有map,filter,sorted等,其中mapfilter返回的是生成器。

allany的用法:

  • all(iterable),如果iterable的每个元素都是真值则返回True,all([])返回True
  • any(iterable),只要iterable有元素为真则返回true,all([])返回False

可调用对象

能使用()的都被叫做可调用对象,可使用callable()判断一个对象是否是可调用对象,python中有7中可调用对象:

  1. 用户定义的函数
  2. 类,调用时会运行__new__方法创建一个实例,然后运行__init__方法初始化实例,最后把实例返回给调用方。
  3. 类的实例,前提是类定义了__call__方法。
  4. 生成器函数,在函数中使用了yieled语句的

用户定义的可调用类型

只需实现__call__方法。

例子,从打乱的列表中取出一个元素

import random

calss 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 BingCage')

def __call__(self):
return self.pick()
>>> bingo = BingoCage(range(6))
>>> bingo.pick()
5
>>> bingo()
4
# bingo.pick()和bingo()的作用是一样的

Wikipedia内省)的定义:
内省是指计算机程序在运行时(Run time)检查对象(Object)类型的一种能力,通常也可以称作运行时类型检查。

通俗来讲就是Python在运行时能够知道这个对象是什么,它能做什么,它包含哪些内容。

一些内省函数

  • dir(object):它返回一个列表,这个列表中包含object的所有属性
  • type:返回一个对象的类型
  • id:返回一个对象的id

获取关于参数的信息

函数对象有个__defaults__属性,它的值是一个元组,里面保存着定位参数和关键字参数的默认值。__kwdefaults__包含仅限关键字参数的默认值。参数的名称在__code__属性中,它的值是一个code对象引用。

函数声明中的各个参数可以在:之后增加注解表达式。如果参数有默认值放在参数名和=之间。如果想添加返回值注解,在)和函数声明末尾:之间添加->和一个表达式。
注解存储在__annotations__属性中

支持函数式编程的包

operator

itmegetterattrgetter会自行构建函数,所起的作用类似于使用lambda表达式从序列中取出元素或者读取对象的属性。

itemgetter
下例利用itemgetter排序一个数组,itemgetter()的作用与lambda fields: fields[1]相同,创建一个接收集合的函数,返回索引位1的元素。

>>> metro_data = [('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),]

>>> 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))

attrgetter

它创建的函数根据名称提取对象的属性,如果把多个属性名传给attrgetter,它也会返回提取的值构成的元组。

例子

>>> 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)
('Delhi NCR', 28.613889)
('Tokyo', 35.689722)

methodcaller

methodcaller创建的函数会在对象上调用参数指定的方法。

例子

>>> from operator import methodcaller
>>> s = 'good good study, day day up'
>>> upcase = methodcaller('upper')
>>> upcase(s)
'GOOD GOOD STUDY, DAY DAY UP'
>>>

使用functools.partial冻结参数

functools.partial这个高阶函数用于部分应用一个函数。部分应用指的是,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。

例子

>>> from operator import mul
>>> from functools import partial
>>> triple = partial(mul,3)
>>> [triple(i) for i in range(6)]
[0, 3, 6, 9, 12, 15]




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK