记录学习《流畅的python》的一些知识-----一等函数(2)

记录我学习《流畅的python》的过程

2021.1.31

1.获取关于参数的信息
在指定长度附近截断字符串的函数:

def clip(text, max_len=80):
    """在max_len前面或后面的第一个空格处截断文本"""
    end = None
    if len(text) > max_len:
        space_before = text.rfind(' ', θ, max_len)
        if space_before >= 0:
            end = space_before
        else:
            space_after = text.rfind(' ', max_len)
            if space_after >= 0:
                end = space_after
        if end is None: # 没有找到空格
            end = len(text)
        return text[:end].rstrip()

print(clip.__defaults__)
print(clip.__code__)
print(clip.__code__.co_varnames)
print(clip.__code__.co_argcount)

在这里插入图片描述
组织信息的方式并不是最便利的,使用inspect是是更好的方式:

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)

在这里插入图片描述
是一个有序映射。
其中有一个bind方法,它可以把任意个参数绑定到签名中的形参,所用的规则与实参到形参的匹配方式一样,框架可以使用这个方法在真正调用函数前验证参数。

import inspect
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  '\n'.join('<%s%s>%s</%s>' %
                          (name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />' % (name, attr_str)

sig = inspect.signature(tag)
my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
          'src': 'sunset.jpg', 'cls': 'framed'}
bound_args = sig.bind(**my_tag)
print(bound_args)

for name, value in bound_args.arguments.items():
    print(name, '=', value)

del my_tag['name']
bound_args = sig.bind(**my_tag)

在这里插入图片描述
2.函数注解
有注解的函数声明和提取函数签名中的注解:

from inspect import signature
def clip(text:str, max_len:'int > 0'=80) -> str:
    """在max_len前面或后面的第一个空格处截断文本"""
    end = None
    if len(text) > max_len:
        space_before = text.rfind(' ', θ, max_len)
        if space_before >= 0:
            end = space_before
        else:
            space_after = text.rfind(' ', max_len)
            if space_after >= 0:
                end = space_after
        if end is None: # 没有找到空格
            end = len(text)
        return text[:end].rstrip()

print(clip.__annotations__)

sig = signature(clip)
print(sig.return_annotation)
for param in sig.parameters.values():
    note = repr(param.annotation).ljust(13)
    print(note, ':', param.name, '=', param.default)

在这里插入图片描述
3.支持函数式编程的包
operator模块
使用reduce函数和一个匿名函数计算阶乘:

from functools import reduce
def fact(n):
    return reduce(lambda a, b: a*b, range(1, n+1))

print(fact(10))

在这里插入图片描述

使用reduce和operator.mul函数计算阶乘:

from functools import reduce
from operator import mul

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

print(fact(10))

在这里插入图片描述
演示使用itemgetter排序一个元组列表,如果把多个参数传给itemgetter,它构建的函数会返回提取的值构成的元组:

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.43333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
from operator import itemgetter
for city in sorted(metro_data, key=itemgetter(1)):
    print(city)

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

在这里插入图片描述
attrgetter与itemgetter作用类似,它创建的函数根据名称提取对象的属性:

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.43333, -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与前两种类似,会自行创建函数。

from operator import methodcaller
s = 'The time has come'
upspace = methodcaller('upper')
print(upspace(s))

hiphenate = methodcaller('replace', ' ', '-')
print(hiphenate(s))

使用functools.partial冻结参数:

from operator import mul
from functools import partial
triple = partial(mul, 3)
print(triple(7))
print(list(map(triple, range(1, 10))))

在这里插入图片描述

使用partial构建一个便利的Unicode规范化函数:

import unicodedata, functools
nfc = functools.partial(unicodedata.normalize, 'NFC')
s1 = 'café'
s2 = 'cafe\u0301'
print(s1, s2)
print(s1 == s2)
print(nfc(s1) == nfc(s2))

在这里插入图片描述
把partial应用到tag函数上:

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  '\n'.join('<%s%s>%s</%s>' %
                          (name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />' % (name, attr_str)

print(tag)

from functools import partial
picture = partial(tag, 'img', cls='pic-frame')
print(picture(src='wumpus.jpeg'))
print(picture)
print(picture.func)
print(picture.args)
print(picture.keywords)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值