流畅的python第5-7章笔记
把函数视作对象
第5章 一等函数
1.在函数式编程范式中,最为人熟知的高阶函数有map
,filter
,reduce
和apply
.函数式语言通常会提供map,filter和reduce三个高阶函数(有时使用不同的名称).在python3中,map和filter还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得没那么重要了.列表推导和生成器表达式具有map和filter两个函数的功能.而且更易于阅读.
2.sum
和reduce
函数用于求和.最好使用sum函数,可读性更好.sum和reduce的通用思想是把某个操作连续应用到序列的元素上,累计之前的结果,把一系列值归约
成一个值.all
和any
也是内置的归约函数
In [2]: from functools import reduce
In [3]: from operator import add
In [4]: reduce(add,range(100))
Out[4]: 4950
In [5]: sum(range(100))
Out[5]: 4950
In [6]: all('niaho')
Out[6]: True
In [7]: all('niaho',['wohao'])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-663ce7255241> in <module>()
----> 1 all('niaho',['wohao'])
TypeError: all() takes exactly one argument (2 given)
In [8]: all(('niaho',['wohao']))
Out[8]: True
In [9]: all(('niaho',['wohao'],''))
Out[9]: False
In [10]: any('niaho')
Out[10]: True
In [12]: any('niaho',['wohao'])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-3e515d3dba5a> in <module>()
----> 1 any('niaho',['wohao'])
TypeError: any() takes exactly one argument (2 given)
In [13]: any(('niaho',['wohao'],''))
Out[13]: True
3.为了使用高阶函数,有时创建一次性的小型函数更便利.这便是匿名函数存在的原因.lambda关键字在python表达式内创建匿名函数.然而,python简单的句法限制了lambda函数的定义体只能使用纯表达式.换句话说,lambda函数的定义体中不能赋值,也不能使用while和try等python语句.eval函数好像也是这样.除了作为参数传给高阶函数之外,python很少使用匿名函数.由于句法上的限制,非平凡的lambda表达式要么难以阅读,要么无法写出.lambda句法只是语法糖:与def语句一样,lambda表达式会创建函数对象
4.python数据模型文档列出了7种可调用对象
- 用户定义的函数.使用def或lambda表达式创建
- 内置函数.使用c语言(cpython)实现的函数,如len或time.strftime
- 内置方法.使用c语言实现的方法,如dict.get
- 方法.在类的定义体中定义的函数
- 类.调用类时会运行类的
__new__
方法创建一个实例,然后运行__init__方法,初始化实例,最后把实例返回给调用方 - 类的实例.如果类定义了
__call__
方法,那么它的实例可以作为函数调用 - 生成器函数.使用
yield
关键字的函数或方法.调用生成器函数返回的是生成器对象,生成器函数还可以作为协程
5.从定位参数到仅限关键字参数
In [17]: my_tag={'name':'img','title':'Sunset Boulevard','src':'sunset.jpg','cls':'framed'}
In [18]: tag(**my_tag)
name is:img
content is:()
cls is:framed
attrs is:{'title': 'Sunset Boulevard', 'src': 'sunset.jpg'}
In [19]: def tag(name,*content,cls=None,**attrs):
...: print("name is:"+name)
...: print("content is:"+str(content))
...: print("cls is:"+str(cls))
...: print("attrs is:"+str(attrs))
...:
...:
In [20]: tag('p','hello')
name is:p
content is:('hello',)
cls is:None
attrs is:{}
In [21]: my_tag={'name':'img','title':'Sunset Boulevard','src':'sunset.jpg','cls':'framed'}
In [22]: tag(**my_tag)
name is:img
content is:()
cls is:framed
attrs is:{'title': 'Sunset Boulevard', 'src': 'sunset.jpg'}
调用tag('p','hello')
时,第一个参数后面的任意个参数会被*content
捕获,存入一个元组
调用tag(**my_tag)
时,在my_tag前面加上**
,字典中的所有元素作为单个参数传入,同名键会绑定到对应的具名参数上,余下的则被**attrs
捕获
6.函数对象有个__defaults__
属性,它的值是一个元组,里面保存着定位参数和关键字参数的默认值.仅限关键字参数的默认值在__kwdefaults__
属性中.然而,参数的名称在__code__
属性中,它的值是一个code对象引用,自身也有很多属性如下
In [31]: def tag(name,*content,cls=666,**attrs):
...: print("name is:"+name)
In [32]: tag.__defaults__
In [33]: tag.__kwdefaults__
Out[33]: {'cls': 666}
In [34]: tag.__code__
Out[34]: <code object tag at 0x102288540, file "<ipython-input-31-7396c504e34a>", line 1>
In [35]: tag.__code__.co_name
Out[35]: 'tag'
In [36]: tag.__code__.co_names
Out[36]: ('print',)
In [37]: tag.__code__.co_varnames
Out[37]: ('name', 'cls', 'content', 'attrs')
In [38]: tag.__code__.co_argcount
Out[38]: 1
第6章 使用一等函数实现设计模式
1.
第7章 函数装饰器和闭包
1.