一等对象

编程语言理论家把“一等对象”定义为满足下述条件的程序实体:在运行是创建

能赋值给变量或数据结构中的元素

能作为参数传给函数 - 能作为函数的返回结果

把函数当作对象

函数都是function类的实例,类的方法是method类的实例(虽然经常会把方法称为函数)

def fun():
pass
class Foo:
def bar(self):
pass
print(type(fun))
>>>
print(type(Foo().bar))
>>>

高阶函数

接受函数为参数或者把函数作为结果返回的函数称为高阶函数。

在函数式编程范式中,最为人熟知的高阶函数有map(), filter(), reduce()

all()和any()

all(iterable), 如果iterable的每个值都为True,返回True any(iterable), 如果iterable存在一个值为True,返回True

匿名函数

使用lambda关键字创建匿名函数,格式为lambda [arg1 [,arg2,.....argn]]:expression,匿名函数的定义体中不能赋值,不能使用while和try语句。

我十分不喜欢用匿名函数,基本没有用过,即使是用高阶函数需要传递函数作为参数时,也是额外用def语句编写函数,所以一直对lambda理解不到位。

匿名函数这样理解:将arg x作为参数传递给expression,得到结果后返回。

Lundh提出的lambda表达式重构秘笈: - (1)编写注释,说明lambda表达式的作用 - (2)研究注释,用一个名称来概括注释 - (3)把lambda表达式改写成def,使用那个名称作为函数名 - (4)删除注释

可调用对象

使用callable()函数可判断是否为可调用对象。python中有7种可调用对象: - 用户使用def和lambda创建的函数 - 内置函数,使用C语言(CPython)实现的函数,如len或time.strftime - 使用C语言实现的方法,如dict.get - 方法,在类的定义体中定义的函数 - 类,调用类时会运行__new__方法创建一个实例,python没有new运算符,所以调用类相当于调用函数 - 定义了__call__()类的实例 - 生成器函数,使用yield关键字的函数或方法

L = [abs, str, 13]
print([callable(x) for x in L])
>>>[True, True, False]

函数内省

函数内省(function introspection)是在运行时进行的一种对象检测机制,用来查看某个对象内部信息,如类的type类型、属性、方法、事件等等。

(内省: 文言,意思是查看内部情况。华夏特色的翻译,恕我直言,把第一个叫这个名字的人拉出去斩了)

python中使用dir()可以获得对象的各种信息。

def fun():
pass
print(dir(fun))
>>>['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

获取关于参数的信息

以我目前水平不能理解作者讲的这些内容有什么作用

函数注解

def clip(text:str, max_len:'int > 0'=80) -> str:
return ''

函数声明中的各个参数可以在:之后增加注解表达式。如果参数有默认值,注解放在参数名和=号之间。如果想注解返回值,在)和函数声明末尾的:之间添加->和一个表达式。这个表达式可以是任何类型,在上面的例子中是str

注解不会做任何处理,只是存储在函数的__annotations__属性(一个字典)中

def clip(text:str, max_len:'int > 0'=80) -> str:
return ''
print(clip.__annotations__)
>>>{'text': , 'max_len': 'int > 0', 'return': }
支持函数式编程的包
from functools import reduce, mul
def fact1(n):
return reduce(lambda a, b: a*b, range(1, n+1))
def fact2(n):
return reduce(mul, range(1, n+1))
operator模块为多个算术运算符提供了对应的函数,从而避免编写lambda a, b: a*b这种平凡的匿名函数
itemgetter和attrgetter

operator模块中还有一类函数,能替代从序列中取出元素或读取对象属性的lambda表达式,如itemgetter和attrgetter

# 将students表按第二个属性升序排列
from operator import itemgetter
students = [
('xiao ming', 77, 180),
('lao wang', 75, 185),
('xiao qing', 100, 183),
]
res = sorted(students, key=itemgetter(1))
print(res)
attrgetter类似
methodcaller
methodcaller创建的函数会在对象上调用参数指定的方法
from operator import methodcaller
s = 'I am a pupil'
f = methodcaller('replace', ' ', '-')
print(f(s))
>>>I-am-a-pupil
functools.partial
from operator import mul
from functools import partial
f = partial(mul, 3)
print(f(7))
>>>21

固定第一个参数为3, 传入7则结果为21