流畅的Python第五章,一等函数笔记(未完,准备从一章开始看)。
作者:互联网
Python中又一个名称叫一等对象,满足以下条件的程序实体:
1、在运行时创建
2、能赋值给变量或数据结构中的元素
3、能作为参数传给函数
4、能作为函数的返回结果
所以Python中,正数、字符串、字典与函数都是一等对象。
5.1把函数当做对象:
把函数当做对象,通过简单的__doc__可以输出函数的说明。
In [55]: def demo(a,b): ...: '''返回a,b''' ...: return a,b ...: In [56]: demo.__doc__ Out[56]: '返回a,b' In [57]:
通过高阶函数把函数传递进去。
def fact(n): '''returns n!''' return 1 if n < 2 else n * fact(n - 1) print(list(map(fact, range(10))))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
fact就是传递进去的函数。
5.2高阶函数
接受函数为参数,或者把函数作为结果返回的函数为高阶函数(hight-order function)。
map,filter,reduce,包括sorted都是高阶,sorted的key可以接收函数.
按照这个定义,我们的闭包函数,装饰器函数,都可以称为高阶函数。
map,filter和reduce的现代替换品
map与filter因为列表生成式的使用,基本很多需要使用他们的地方都可以用列表生成式。
def fact(n): '''returns n!''' return 1 if n < 2 else n * fact(n - 1) ''' 接收函数为参数,或者把函数作为结果返回的函数是高阶函数。 所以,map,filter,reduce,sorted(因为key能接收函数) ''' print(fact(10)) print(list(map(fact, range(10)))) # map需要传入函数fact print([fact(i) for i in range(10)]) # 直接列表生成式,每个参数直接使用了函数fact,产生的返回值放入列表。 print(list(map(fact, filter(lambda n : n % 2, range(10))))) # 在map的函数后面的可迭代对象进行了filter的过滤,需要能被2整除 # filter第一个只返回:后面条件成立的数值。 def condition(n): if n % 2 != 0: return n print(list(map(fact, filter(condition, range(10))))) print([fact(i) for i in range(10) if i % 2]) # 列表生成式第一个写函数或者参数,第二个写循环体,第三个写条件。 # 书中直接写if i % 2应该就是! % 2不能为0,这个写法更加精简。所以以后条件如果返回只要是真,写入就可以,生成的时候就会执行。 print([fact(i) for i in range(10) if i % 2 !=0]) # 如果我写,我一半写成这样。
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/高级函数.py 3628800 [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] [1, 6, 120, 5040, 362880] [1, 6, 120, 5040, 362880] [1, 6, 120, 5040, 362880] Process finished with exit code 0
reduce现在用的很少,一般用在求和上面。
from functools import reduce from operator import add def s_add(x, y): return x + y print(reduce(add, range(100))) print(reduce(s_add, range(100))) print(sum(range(100)))
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t5.2.py 4950 4950 4950 Process finished with exit code 0
归约函数all,any是蛮好的函数.
all(iterable) 里面的可迭代对象全部为真返回真。(有点像and)
any(iterable) 有一个真就返回真。 (有点像or)
a1 = '1232434' a2 = [1, 2, 3, 0] a3 = {'name': 'sidian', 'age': None} a4 = (None, 9, 8) print(a1, all(a1), any(a1)) print(a2, all(a2), any(a2)) print(a3, all(a3), any(a3)) print(a4, all(a4), any(a4))
1232434 True True [1, 2, 3, 0] False True {'name': 'sidian', 'age': None} True True (None, 9, 8) False True
5.3匿名函数
lambda是Python表达式内创建匿名函数。然而Python简单的语法限制了lambda函数的定义题只能使用纯表达式。换句话说,lambda函数的定义体中不能赋值,也不能使用while和try等Python语句。
lambda(init:return),lambda函数通过分号相隔,前面是输入参数,后面是返回参数。
lambda语法是语法糖,更def一样,会创建可以调用的函数对象。
5.4可调用对象
可调用对象就是能用()的对像(里面有__call__的方法),可以用callable来测试是否是可调用对象,Python数据模型里面有7种可调用对象。
1、用户定义的函数
比如使用def或者lambda创建的对象。
2、内置函数
使用C语言显示的函数,比如len或time.strftime
3、内置方法
使用C语言实现的方法,比如dict.get
4、方法
在类的实体中定义的函数
5、类
在实例化类的使用,首先调用的是__call__,然后调用__new__创建对象,最后__init__来初始化对象。
6、类的实例
在类里面定义了__call__,那么实例就可以成为调用对象。
7、生成器
调用生成器函数可以返回一个生成器对象。
5.5 用户定义的可调用类型。
通过类里面给予定义函数__call__
import random class BingCage: 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 BingoCage') def __call__(self, *args, **kwargs): # 让对象拥有call方法,能直接被调用 return self.pick() bingo = BingCage('abc') for i in range(5): try: print(bingo.pick()) except LookupError as e: print(e)
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t_5.5.py b c a pick from empty BingoCage pick from empty BingoCage Process finished with exit code 0
5.6 函数内省
函数有很多属性,我们通过dir来查看。
dir(lambda x : x[2]) Out[57]: ['__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__']
首先说一个,函数对象有__dict__属性,所以可以通过.或者setattr来进行属性赋值,这个我以前还真不知道。(但一般很少对函数对象进行属性赋值)
def demo(): ...: ... ...: In [63]: demo.abc = 'abc' In [64]: demo.__dict__ Out[64]: {'abc': 'abc'} In [65]: setattr(demo,'name','sidian') In [66]: demo.name Out[66]: 'sidian' In [67]: demo.__dict__ Out[67]: {'abc': 'abc', 'name': 'sidian'} In [68]:
下面列出函数独有,但对象没有的属性,我准备跟类也对比一下。
class C: ... def func(): ... c = C() print(set(dir(C)) - set(dir(func))) print(set(dir(func)) - set(dir(C))) print(set(dir(c)) - set(dir(func))) print(set(dir(func)) - set(dir(c)))
/usr/local/bin/python3.7 /Users/shijianzhong/study/Fluent_Python/第五章/t_5.6.py {'__weakref__'} {'__annotations__', '__get__', '__globals__', '__call__', '__name__', '__qualname__', '__code__', '__kwdefaults__', '__defaults__', '__closure__'} {'__weakref__'} {'__annotations__', '__get__', '__globals__', '__call__', '__name__', '__qualname__', '__code__', '__kwdefaults__', '__defaults__', '__closure__'} Hello sidian Process finished with exit code 0
从中可以看出来,对象或者类比函数对了一个属性__weakref__,我查了一些资料好像是关于垃圾回收相关,具体资料很少。
https://stackoverflow.com/questions/36787603/what-exactly-is-weakref-in-python这个链接有一些英文的答案。
但函数比对象多了很多属性。
标签:__,一章,函数,Python,range,第五章,def,print,fact 来源: https://www.cnblogs.com/sidianok/p/12044154.html