第5章--一等函数

第5章–一等函数

一等对象定义为满足以下条件的程序实体

  1. 在运行时创建
  2. 能赋值给变量或者数据结构中的元素
  3. 能作为参数传给函数
  4. 能作为函数的返回结果

python中函数就是一等对象,简称一等函数

5.1 把函数视为对象

函数是一个对象,自定义的函数是函数对象的一个实例,函数对象有一些默认的属性,比如__doc__

def factorial(n):
    '''return n!'''
    return 1 if n<2 else n*factorial(n-1)

print(factorial(5)) # 120
print(factorial.__doc__) # return n!
print(type(factorial)) #<class 'function'>

5.2 高阶函数

接受函数为参数,或者把函数作为结果返回的函数是高阶函数(higher-order function)。
map、sorted、filter就是高阶函数

map、filter可以用列表推导式替代

5.3 匿名函数

lambda,只能写一些简单函数,适合用在参数传入一个函数对象时

5.4 可调用对象

python有七种可调用对象

  1. 用户自定义函数,def语句或lambda定义的函数
  2. 内置函数 使用 C 语言(CPython)实现的函数,如 len 或 time.strftime
  3. 内置方法 使用 C 语言实现的方法,如 dict.get。
    上面二者的差异是方法是某个类里面的函数,函数则是不在类里面的
  4. 方法
  5. 类,生成类的实例时其实就是call 类的一个过程
  6. 类的实例,如果类定义了__call__方法,那么它的实例可以作为函数调用
  7. 生成器函数,使用yield返回的函数或方法

https://stackoverflow.com/questions/111234/what-is-a-callable 这里的回答在cpython代码的侧面来解释callable函数的判断,callable(x)如果要返回True,要满足下面两个条件之一

  1. x是类的实例,并且类实现了__call__方法
  2. x->ob_type->tp_call != NULL

5.5 用户定义的可调用类型

自定义类实现__call__方法就行,略

5.6 函数内省

函数有很多内置的属性,列举如下
[’__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__’]

函数专有而自定义类没有的属性
在这里插入图片描述

5.7

函数参数中用* 可以让后面的参数必须以关键字的形式传入,用*而不是a=1这样的形式是可以用不用默认值的关键字参数

def f(*,a,b):
    return a,b
print(f(a=1,b=2))# 1,2
print(f(1,b=2))
# TypeError: f() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given

5.8 获取关于参数的信息

可以用inspect.signature函数获取函数参数的信息

from inspect import signature
def f(a,b=1):
    return a,b

sig=signature(f)
print(sig) #(a, b=1)
for name,param in sig.parameters.items():
    print(param.kind," : ",name,param.default)
# POSITIONAL_OR_KEYWORD  :  a <class 'inspect._empty'>
# POSITIONAL_OR_KEYWORD  :  b 1

kind属性的值是_ParameterKind 类中的 5 个值之一

  1. POSITIONAL_OR_KEYWORD可以通过定位参数和关键字参数传入的形参(多数 Python 函数的参数属于此类)。
  2. VAR_POSITIONAL 定位参数元组。
  3. VAR_KEYWORD 关键字参数字典。
  4. KEYWORD_ONLY 仅限关键字参数(Python 3 新增)。
  5. POSITIONAL_ONLY 仅限定位参数;目前,Python 声明函数的句法不支持,但是有些使用 C 语言实现且不接受关键字参数的函数(如 divmod)支持。

signature.bind()方法可以把实参绑定到形参上,可以用于调用函数前对函数调用的参数正确性的判断

from inspect import signature

def f(a,b):
    return a,b

input_params={'a':1,'b':2}
sig=signature(f)
sig.bind(**input_params)
del input_params['a']
sig.bind(**input_params) # TypeError: missing a required argument: 'a'

5.9 函数注解

from inspect import signature
def f(a:int,b:'int>0'=1)->(int,int):
    return a,b

sig=signature(f)
print(sig) #(a:int, b:'int>0'=1) -> (<class 'int'>, <class 'int'>)
for name,param in sig.parameters.items():
    print(param.kind," : ",name,param.default)
# POSITIONAL_OR_KEYWORD  :  a <class 'inspect._empty'>
# POSITIONAL_OR_KEYWORD  :  b 1

python对函数注解的唯一操作是把他们放到函数的__annotations__属性里,不会做任何的验证和检查,函数注解方便了ide的静态类型检查

5.10 支持函数式编程的包

  • operator模块,在函数式编程中,经常要把算术运算符当函数用,operator模块提供了算术运算符对应的函数,还提供了替代从序列中获取元素或者读取对象属性的函数itemgetter和attrgetter

  • functools.partial 可以用来固定参数,

from operator import mul
from functools import partial
triple=partial(mul,3)
print(triple(7)) #21
发布了51 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36267931/article/details/102826984