资讯专栏INFORMATION COLUMN

流畅的python读书笔记-第五章 一等函数

546669204 / 3195人阅读

摘要:可以通过定位参数和关键字参数传入的形参多数函数的参数属于此类。就像数据格式化一样数据带上标签自行创建函数它会自行创建函数。创建的函数会在对象上调用参数指定的方法自己创建函数冻结参数这个高阶函数用于部分应用一个函数。

高阶函数
接受函数为参数,或者把函数作为结果返回的函数是高阶函数
    def reverse(word):
        return word[::-1]
    
    
    fruits = ["strawberry", "fig", "apple", "cherry", "raspberry", "banana"]
    
    print(reverse("testing"))
    
    print(sorted(fruits, key=reverse))
all 和 any 也是内置的归约函数。
all(iterable)

如果 iterable 的每个元素都是真值,返回 True;all([]) 返回True。

any(iterable)

只要 iterable 中有元素是真值,就返回 True;any([]) 返回False。

匿名函数
fruits = ["strawberry", "fig", "apple", "cherry", "raspberry", "banana"]

print(sorted(fruits, key=lambda word: word[::-1]))
可调用对象

如果类定义了 call 方法,那么它的 实例 可以作为函数调用。

因此判断对象能否调用,最安全的方法是使用内置的 callable() 函数

实现 call 方法的类是创建函数类对象的简便方式,

函数内省

用户定义的函数的属性 page 252

案例 生成html标签的函数
def tag(name, *content, cls=None, **attrs):
    """生成一个或多个HTML标签"""

    if cls is not None:
        attrs["class"] = cls

    if attrs:
        attr_str = "".join(" %s="%s"" % (attr, value)
                           for attr, value
                           in sorted(attrs.items()))
    else:
        attr_str = ""

    if content:
        return "
".join("<%s%s>%s" % (name, attr_str, c, name) for c in content)
    else:
        return "<%s%s />" % (name, attr_str)


print(tag("br"))

print(tag("p", "hello"))

print(tag("p", "hello", "world"))

print(tag("p", "hello", "world", cls="sidebar")) 
获取关于参数的信息
import bobo
@bobo.query("/")
def hello(person):
return "Hello %s!" % person

bobo.query 装饰器把一个普通的函数(如 hello)与框架的请求处理
机制集成起来了。

Bobo 会内省 hello 函数,发现它需要一个名为 person
的参数,然后从请求中获取那个名称对应的参数,将其传给 hello 函
数,因此程序员根本不用触碰请求对象。

提取关于函数参数的信息

使用 inspect 模块

from clip import clip
from inspect import signature
sig = signature(clip)

print(sig)


print(str(sig))

for name, param in sig.parameters.items():
    print(param.kind, ":", name, "=", param.default)

inspect.signature 函数返回一个inspect.Signature 对象

它有一个 parameters 属性,这是一个有序映射,

把参数名和 inspect.Parameter 对象对应起来。

各个Parameter 属性也有自己的属性,

例如 name、default 和 kind。特殊的 inspect._empty 值表示没有默认值

kind 属性的值是 _ParameterKind 类中的 5 个值之一,列举如下。

POSITIONAL_OR_KEYWORD

可以通过定位参数和关键字参数传入的形参(多数 Python 函数的参数属于此类)。

VAR_POSITIONAL

定位参数元组。

VAR_KEYWORD

关键字参数字典。

KEYWORD_ONLY

仅限关键字参数(Python 3 新增)。

POSITIONAL_ONLY

仅限定位参数;

inspect.Signature 对象有个 bind 方法,

它可以把任意个参数绑定到签名中的形参上,所用的规则与实参到形参的匹配方式一样。
框架可以使用这个方法在真正调用函数前验证参数,

示例 5-18 把tag 函数(见示例 5-10)的签名绑定到一个参数字典

>>> import inspect
>>> sig = inspect.signature(tag) ➊
>>> my_tag = {"name": "img", "title": "Sunset Boulevard",
... "src": "sunset.jpg", "cls": "framed"}
>>> bound_args = sig.bind(**my_tag) ➋
>>> bound_args
 ➌
>>> for name, value in bound_args.arguments.items(): ➍
... print(name, "=", value)
...
name = img
cls = framed
attrs = {"title": "Sunset Boulevard", "src": "sunset.jpg"}
>>> del my_tag["name"] ➎
>>> bound_args = sig.bind(**my_tag) ➏
Traceback (most recent call last):
...
TypeError: "name" parameter lacking default value

❷ 把一个字典参数传给 .bind() 方法。
❸ 得到一个 inspect.BoundArguments 对象。
❹ 迭代 bound_args.arguments(一个 OrderedDict 对象)中的元
素,显示参数的名称和值。
❺ 把必须指定的参数 name 从 my_tag 中删除。
❻ 调用 sig.bind(**my_tag),抛出 TypeError,抱怨缺少 name 参
数。

函数注解
def clip(text: str, max_len: "int > 0" = 80) -> str:
    print(text, max_len)


clip("sdf", 18)

print(clip.__annotations__)

如果想注解返回值,在 ) 和函数声明末尾的 : 之间添加 -> 和一个表达式。

各个参数可以在 : 之后增加注解表达式。如果参数有默认值,注解放在参数名和 = 号之间。

注解不会做任何处理,只是存储在函数的 annotations 属性(一
个字典)中:
operator模块 reduce计算阶乘
from functools import reduce


# 阶乘
def fact(n):
    print(reduce(lambda a, b: a * b, range(1, n + 1)))


# operator.mul 函数计算阶乘
from functools import reduce
from operator import mul


def fact2(n):
    return reduce(mul, range(1, n + 1))

print(fact2(3))
itemgetter

展示了 itemgetter 的常见用途:根据元组的某个字段给元
组列表排序。在这个示例中,按照国家代码(第 2 个字段)的顺序打印
各个城市的信息。

metro_data = [
    ("Tokyo", "JP", 36.933, (35.689722, 139.691667)),
    ("Delhi NCR", "IN", 21.935, (28.613889, 77.208889)),
    ("Mexico City", "MX", 20.142, (19.433333, -99.133333)),
    ("New York-Newark", "US", 20.104, (40.808611, -74.020386)),
    ("Sao Paulo", "BR", 19.649, (-23.547778, -46.635833)),
]

### 演示使用 itemgetter 排序一个元组列表

from operator import itemgetter

for city in sorted(metro_data, key=itemgetter(1)):
    print(city)

如果把多个参数传给 itemgetter,它构建的函数会返回提取的值构成
的元组:

cc_name = itemgetter(1, 0)
for city in metro_data:
    print(cc_name(city))
attrgetter

此外,如果参数名中包含 .(点号),attrgetter 会深
入嵌套对象,获取指定的属性。

from collections import namedtuple

metro_data = [
    ("Tokyo", "JP", 36.933, (35.689722, 139.691667)),
    ("Delhi NCR", "IN", 21.935, (28.613889, 77.208889)),
    ("Mexico City", "MX", 20.142, (19.433333, -99.133333)),
    ("New York-Newark", "US", 20.104, (40.808611, -74.020386)),
    ("Sao Paulo", "BR", 19.649, (-23.547778, -46.635833)),
]

## 就像数据格式化一样 数据带上标签
LatLong = namedtuple("LatLong", "lat long")

Metropolis = namedtuple("Metropolis", "name cc pop coord")

metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long))
               for name, cc, pop, (lat, long) in metro_data]

print(metro_areas[0])
print(metro_areas[0].coord.lat)

#
from operator import attrgetter

name_lat = attrgetter("name", "coord.lat")

for city in sorted(metro_areas, key=attrgetter("coord.lat")):
    print(name_lat(city))
methodcaller 自行创建函数

它会自行创建函数。methodcaller 创建的函数会在对象上调用参数指定的方法
自己创建函数

from operator import methodcaller
s = "The time has come"
upcase = methodcaller("upper")

print(upcase)

hiphenate = methodcaller("replace", " ", "-")
print(hiphenate(s))
functools.partial冻结参数
functools.partial 这个高阶函数用于部分应用一个函数。部分应用
是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。
from operator import mul
from functools import partial

print(mul(3, 7))
# 第一个函数, 第二个固定的参数
triple = partial(mul, 3)
print(list(map(triple, range(1, 10))))
小总结 高阶函数

接受函数为参数,或者把函数作为结果返回的函数是高阶函数.

Python 中常用的高阶函数有内置函数

sorted、min、max 和 functools. partial

实例 直接函数化运行

从 lambda 表达式创建的简单函数到实现__call__ 方法的类实例。

这些可调用对象都能通过内置的callable() 函数检测。

函数注解

在 inspect 模块的帮助下,可以读取它们。

例如,Signature.bind 方法使用灵活的规则把实参绑定到形参上,这与 Python 使用的规则一样。

operator 模块

介绍了 operator 模块中的一些函数,

以及functools.partial 函数,

有了这些函数,函数式编程就不太需要功能有限的 lambda 表达式了

其他

all 和 any 也是内置的归约函数.

用来判断是否所有都为真,或者有一个为真

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41640.html

相关文章

  • 流畅python读书笔记-第六章-使用一等函数实现设计模式

    摘要:在复杂的情况下,需要具体策略维护内部状态时,可能需要把策略和享元模式结合起来。函数比用户定义的类的实例轻量,而且无需使用享元模式,因为各个策略函数在编译模块时只会创建一次。 一等函数实现设计模式 经典的策略模式定义 定义一系列算法,把它们一一封装起来,并且使它们可以相互替换。本模式使得算法可以独立于使用它的客户而变化。 案例 假如一个网店制定了下述折扣规则。 有 1000 或以上积分...

    cnsworder 评论0 收藏0
  • JS高程读书笔记--五章引用类型

    摘要:高程读书笔记第五章类型创建实例的方式有两种。第一种是使用操作符后跟构造函数,另一种方式是使用对象字面量表示法。 JS高程读书笔记--第五章 Object类型 创建Object实例的方式有两种。第一种是使用new操作符后跟Object构造函数,另一种方式是使用对象字面量表示法。 在通过对象字面量定义对象时,实际上不会调用Object构造函数 访问对象属性时可以使用点表示法和方括号表示法。...

    anRui 评论0 收藏0
  • 《java 8 实战》读书笔记 -五章 使用流

    摘要:比如,你可以建立一个,选出热量超过卡路里的头三道菜请注意也可以用在无序流上,比如源是一个。跳过元素流还支持方法,返回一个扔掉了前个元素的流。一般来说,应该使用来对这种流加以限制,以避免打印无穷多个值。 一、筛选和切片 1.用谓词筛选 Streams接口支持filter方法。该操作会接受一个谓词(一个返回boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。例如筛选出所有...

    Richard_Gao 评论0 收藏0
  • 《Java8实战》-五章读书笔记(使用流Stream-01)

    摘要:跳过元素流还支持方法,返回一个扔掉了前个元素的流。归约到目前为止,我们见到过的终端操作都是返回一个之类的或对象等。这样的查询可以被归类为归约操作将流归约成一个值。通过反复使用加法,你把一个数字列表归约成了一个数字。 使用流 在上一篇的读书笔记中,我们已经看到了流让你从外部迭代转向内部迭代。这样,你就用不着写下面这样的代码来显式地管理数据集合的迭代(外部迭代)了: /** * 菜单 ...

    OldPanda 评论0 收藏0
  • 《Java8实战》-五章读书笔记(使用流Stream-02)

    摘要:第三个问题查找所有来自于剑桥的交易员,并按姓名排序。第六个问题打印生活在剑桥的交易员的所有交易额。第八个问题找到交易额最小的交易。 付诸实战 在本节中,我们会将迄今学到的关于流的知识付诸实践。我们来看一个不同的领域:执行交易的交易员。你的经理让你为八个查询找到答案。 找出2011年发生的所有交易,并按交易额排序(从低到高)。 交易员都在哪些不同的城市工作过? 查找所有来自于剑桥的交易...

    liangzai_cool 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<