fluent python- 第 5 章 一等函数-面向对象(附第四章-文本和字节序列)

第 4 章 文本和字节序列

人类使用文本, 计算机使用字节序列。


第 5 章 一等函数

前言:

在 Python 中, 函数是一等对象。 编程语言理论家把“一等对象”定义为满足下述条件的程序实体:
1、在运行时创建
2、能赋值给变量或数据结构中的元素
3、能作为参数传给函数
4、能作为函数的返回结果


5.1 把函数视作对象

map、 filter和reduce的现代替代品
函数式语言通常会提供 map、 filter 和 reduce 三个高阶函数( 有时使用不同的名称) 。 在 Python 3 中, map 和 filter 还是内置函数, 但是由于引入了列表推导和生成器表达式, 它们变得没那么重要了。 列表推导或生成器表达式具有 map 和 filter 两个函数的功能, 而且更易于阅读, 如示例:

>>> list(map(fact, range(6))) ➊   # fact是一个提前定义好的阶乘函数n!
[1, 1, 2, 6, 24, 120]
>>> [fact(n) for n in range(6)] ➋
[1, 1, 2, 6, 24, 120]
>>> list(map(factorial, filter(lambda n: n % 2, range(6)))) ➌
[1, 6, 120]
>>> [factorial(n) for n in range(6) if n % 2] ➍
[1, 6, 120]
>>>


5.3 匿名函数

Python 简单的句法限制了 lambda 函数的定义体只能使用纯表达
式。 换句话说, lambda 函数的定义体中不能赋值, 也不能使用 while
和 try 等 Python 语句,在参数列表中最适合使用匿名函数。

>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

除了作为参数传给高阶函数之外, Python 很少使用匿名函数。 由于句法上的限制, 非平凡的 lambda 表达式要么难以阅读, 要么无法写出.


5.4 可调用对象

除了用户定义的函数, 调用运算符( 即 ()) 还可以应用到其他对象
上。 如果想判断对象能否调用, 可以使用内置的 callable() 函数。
Python 数据模型文档列出了 7 种可调用对象:

  1. 用户定义的函数:使用 def 语句或 lambda 表达式创建。
  2. 内置函数
  3. 内置方法
  4. 方法
  5. 类的实例
  6. 生成器函数

5.5 用户定义的可调用类型

不仅 Python 函数是真正的对象, 任何 Python 对象都可以表现得像函
数。 为此, 只需实现实例方法 __call__

import random
class BingoCage:
    def __init__(self, items):
        self._items = list(items)
        random.shuffle(self._items)   # 随机洗牌
    def pick(self):
        try:  # list = [1,2,3]; list.pop()结果为3,再输入list,结果为[1,2]
            return self._items.pop()
        except ImportError:
            raise LookupError('pick from empty BigoCate')
    def __call__(self):
        return self.pick()  # 实现bingo.pick() 的快捷方式是 bingo()

bingo = BingoCage(range(3))
print( bingo.pick() )   # 结果:0 or 1 or 2
print( bingo() )   # 上方已经定义了随机洗牌 ; ⚠️bingo已经是实例,我们还可以 实例(),表现的像函数 
print( callable(bingo) )  # True


5.6 函数内省

除了__doc__, 函数对象还有很多属性。 使用 dir 函数可以探知
factorial(已定义的一个函数) 具有下述属性:

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

列出常规对象没有而函数有的属性

>>> class C: pass # ➊
>>> obj = C() # ➋
>>> def func(): pass # ➌
>>> sorted(set(dir(func)) - set(dir(obj))) # ➍
['__annotations__', '__call__', '__closure__', '__code__', '__defaults__',
'__get__', '__globals__', '__kwdefaults__', '__name__', '__qualname__']
>>>

➊ 创建一个空的用户定义的类。
➋ 创建一个实例。
➌ 创建一个空函数。
➍ 计算差集, 然后排序, 得到类的实例没有而函数有的属性列表。


5.7 从定位参数到仅限关键字参数

*args 参数会被存入一个元组
**kwargs 参数会被存入一个字典


5.11 本章小结

本章的目标是探讨 Python 函数的一等本性。 这意味着, 我们可以把函数赋值给变量、 传给其他函数、 存储在数据结构中, 以及访问函数的属性, 供框架和一些工具使用。 高阶函数是函数式编程的重要组成部分,即使现在不像以前那样经常使用 map、 filter 和 reduce 函数了, 但是还有列表推导( 以及类似的结构, 如生成器表达式) 以及 sum、 all和 any 等内置的归约函数。 Python 中常用的高阶函数有内置函数sortedminmaxfunctools. partial

Python 有 7 种可调用对象, 从 lambda 表达式创建的简单函数到实现__call__ 方法的类实例。 这些可调用对象都能通过内置的callable() 函数检测。 每一种可调用对象都支持使用相同的丰富句法声明形式参数, 包括仅限关键字参数和注解——二者都是 Python 3 引入的新特性。

Python 函数及其注解有丰富的属性, 在 inspect 模块的帮助下, 可以读取它们。 例如, Signature.bind 方法使用灵活的规则把实参绑定到形参上, 这与 Python 使用的规则一样。

最后, 本章介绍了 operator 模块中的一些函数, 以及
functools.partial 函数, 有了这些函数, 函数式编程就不太需要功
能有限的 lambda 表达式了。


杂谈

Python 是函数式语言吗?

编程语言“范式”已近末日, 它们是旧时代的遗留物, 令人厌烦。 既然现代语言的设计者对范式不屑一顾, 那么我们的课程为什么要像奴隶一样对其言听计从?

在那篇论文中, 下面这一段点名提到了 Python:
对 Python、 Ruby 或 Perl 这些语言还要了解什么呢? 它们的设
计者没有耐心去精确实现林奈层次结构; 设计者按照自己的意
愿从别处借鉴特性, 创建出完全无视过往概念的大杂烩。
Krishnamurthi 指出, 不要试图把语言归为某一类; 相反, 把它们视
作特性的聚合更有用。
为 Python 提供一等函数打开了函数式编程的大门, 不过这并不是
Guido 的目的。 他在“Origins of Python's Functional Features”一文
http://python-history.blogspot.com/2009/04/origins-of-pythonsfunctional-features.html) 中说, map、 filter 和 reduce 的最初目的是为 Python 增加 lambda 表达式。 这些特性都由 Amrit Prem 贡献, 添加在 1994 年发布的 Python 1.0 中( 参见 CPython 源码中的
Misc/HISTORY 文件,https://hg.python.org/cpython/file/default/Misc/HISTORY) 。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容

  • http://python.jobbole.com/85231/ 关于专业技能写完项目接着写写一名3年工作经验的J...
    燕京博士阅读 7,545评论 1 118
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,134评论 9 118
  • 原文链接:https://github.com/EasyKotlin 值就是函数,函数就是值。所有函数都消费函数,...
    JackChen1024阅读 5,941评论 1 17
  • Python进阶框架 希望大家喜欢,点赞哦首先感谢廖雪峰老师对于该课程的讲解 一、函数式编程 1.1 函数式编程简...
    Gaolex阅读 5,486评论 6 53
  • 本文翻译自Functional Programming Howto 本文将介绍Python中函数式编程的特性。在对...
    大蟒传奇阅读 2,596评论 4 14