流畅的python第5-7章笔记

on under python
1 minute read

把函数视作对象

第5章 一等函数

1.在函数式编程范式中,最为人熟知的高阶函数有map,filter,reduceapply.函数式语言通常会提供map,filter和reduce三个高阶函数(有时使用不同的名称).在python3中,map和filter还是内置函数,但是由于引入了列表推导和生成器表达式,它们变得没那么重要了.列表推导和生成器表达式具有map和filter两个函数的功能.而且更易于阅读.

2.sumreduce函数用于求和.最好使用sum函数,可读性更好.sum和reduce的通用思想是把某个操作连续应用到序列的元素上,累计之前的结果,把一系列值归约成一个值.allany也是内置的归约函数

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.

python
home
github
archive
category