首页 > 编程语言 >《流畅的python》单分派泛函数

《流畅的python》单分派泛函数

时间:2023-04-25 20:34:03浏览次数:47  
标签:流畅 函数 python register 分派 Python singledispatch 类型 htmlize

假设我们在开发一个调试Web应用的工具,我们想生成HTML,显示不同类型的Python对象。我们可能会编写这样的函数:

import html
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)

这个函数适用于任何Python类型,但是现在我们想做个扩展,让它使用特别的方式显示某些类型。

str:把内部的换行符替换为'<br>\n';不使用<pre>,而是使用<p>。

int:以十进制和十六进制显示数字。

list:输出一个HTML列表,根据各个元素的类型进行格式化。

因为Python不支持重载方法或函数,所以我们不能使用不同的签名定义htmlize的变体,也无法使用不同的方式处理不同的数据类型。在Python中,一种常见的做法是把htmlize变成一个分派函数,使用一串if/elif/elif,调用专门的函数,如htmlize_str、htmlize_int,等等。这样不便于模块的用户扩展,还显得笨拙:时间一长,分派函数htmlize会变得很大,而且它与各个专门函数之间的耦合也很紧密。Python 3.4新增的functools.singledispatch装饰器可以把整体方案拆分成多个模块,甚至可以为你无法修改的类提供专门的函数。使用@singledispatch装饰的普通函数会变成泛函数(generic function):根据第一个参数的类型,以不同方式执行相同操作的一组函数。

示例7-21 singledispatch创建一个自定义的htmlize.register装饰器,把多个函数绑在一起组成一个泛函数

from functools import singledispatch
from collections import abc
import numbers
import html
@singledispatch  ➊
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)
@htmlize.register(str)  ➋
def _(text):            ➌
    content = html.escape(text).replace('\n', '<br>\n')
    return '<p>{0}</p>'.format(content)
@htmlize.register(numbers.Integral)  ➍
def _(n):
    return '<pre>{0} (0x{0:x})</pre>'.format(n)
@htmlize.register(tuple)  ➎
@htmlize.register(abc.MutableSequence)
def _(seq):
    inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
    return '<ul>\n<li>'+inner+'</li>\n</ul>'

 

❶ @singledispatch标记处理object类型的基函数。❷ 各个专门函数使用@«base_function».register(«type»)装饰。❸ 专门函数的名称无关紧要;_是个不错的选择,简单明了。❹ 为每个需要特殊处理的类型注册一个函数。numbers.Integral是int的虚拟超类。❺ 可以叠放多个register装饰器,让同一个函数支持不同类型。

只要可能,注册的专门函数应该处理抽象基类(如numbers.Integral和abc.MutableSequence),不要处理具体实现(如int和list)。这样,代码支持的兼容类型更广泛。例如,Python扩展可以子类化numbers.Integral,使用固定的位数实现int类型。

[插图]使用抽象基类检查类型,可以让代码支持这些抽象基类现有和未来的具体子类或虚拟子类。

singledispatch机制的一个显著特征是,你可以在系统的任何地方和任何模块中注册专门函数。如果后来在新的模块中定义了新的类型,可以轻松地添加一个新的专门函数来处理那个类型。此外,你还可以为不是自己编写的或者不能修改的类添加自定义函数。singledispatch是经过深思熟虑之后才添加到标准库中的,它提供的特性很多,这里无法一一说明。这个机制最好的文档是“PEP 443—Single-dispatch generic functions”。[插图]

@singledispatch不是为了把Java的那种方法重载带入Python。在一个类中为同一个方法定义多个重载变体,比在一个函数中使用一长串if/elif/elif/elif块要更好。但是这两种方案都有缺陷,因为它们让代码单元(类或函数)承担的职责太多。@singledispath的优点是支持模块化扩展:各个模块可以为它支持的各个类型注册一个专门函数。

装饰器是函数,因此可以组合起来使用(即,可以在已经被装饰的函数上应用装饰器,如示例7-21所示)。

def escape(s, quote=True):
"""
Replace special characters "&", "<" and ">" to HTML-safe sequences.
If the optional flag quote is true (the default), the quotation mark
characters, both double quote (") and single quote (') characters are also
translated.
"""
s = s.replace("&", "&amp;") # Must be done first!
s = s.replace("<", "&lt;")
s = s.replace(">", "&gt;")
if quote:
s = s.replace('"', "&quot;")
s = s.replace('\'', "&#x27;")
return s

标签:流畅,函数,python,register,分派,Python,singledispatch,类型,htmlize
From: https://www.cnblogs.com/bravesunforever/p/17353749.html

相关文章

  • Python面向切面编程-语法层面和functools模块
    1,Python语法层面对面向切面编程的支持(方法名装饰后改变为log)__author__='Administrator'importtimedeflog(func):defwrapper(*args):start=time.time()func(args)end=time.time()print'funcusedtimeis:',end-st......
  • Python中 os.popen、os.system和subprocess.popen方法介绍
    Python提供了多种与操作系统交互的方法,比如os模块中的popen和system方法,此外,Pythonsubprocess模块中的Popen类也提供了与操作系统交互的方法,使用起来更加灵活,本文将简单介绍这几种方法。目录os.popen方法os.system方法susbprocess.Popen方法替代os.popen()方法替代os.system......
  • python整理
                      ---python异步处理---1,第一类面向切面AsyncMixin:异步处理基类,包含queue和thread元组async_thread:异步method处理类,将方法加入到AsyncMixin的queue中async_class:异步class包装类,对class指定的异步method元组......
  • python线程池设计
    什么是线程池?诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服......
  • Python Selenium搭建UI自动化测试框架
    自动化测试是软件测试中非常重要的一部分,可以提高测试效率和测试覆盖率。在UI自动化测试中,Selenium是非常流行的工具。本文将介绍如何使用Python和Selenium搭建UI自动化测试框架。一、环境准备在开始搭建UI自动化测试框架之前,需要先安装Python和Selenium。可以从Python官网下载P......
  • 安装python
    1.ubautu系统sudoapt-getinstallpython2.7sudoapt-getinstallpython3 卸装sudoapt-getremovepython3卸载Python3.6及其依赖sudoapt-getremove--auto-removepython3.6 3.将python命令映射到python3sudoaptinstallpython-is-python3 ......
  • Python模拟动态星空
    文章目录前言一、模拟星空总结前言今天,我们来用Python做个星空。一、模拟星空1,.首先导入所需要的库:fromturtleimport*fromrandomimportrandom,randint2.初始画面:screen=Screen()width,height=800,600screen.setup(width,height)screen.title('模拟3D星空')scre......
  • 【NLP教程】用python调用百度AI开放平台进行情感倾向分析
    目录一、背景二、操作步骤2.1创建应用2.2获取token2.3情感倾向分析三、其他情感分析四、讲解视频一、背景Hi,大家!我是@马哥python说,一名10年程序猿。今天我来演示一下:通过百度AI开放平台,利用python调用百度接口进行中文情感倾向分析,并得出情感极性分为积极、消极还是中性以......
  • Python pandas读取csv文件时数字变成科学计数法(含有e)
    字段内容比较长时,Python读取会变成变成科学计数法(含有e)像这样importpandasaspsdata=ps.read_csv(r"E:\AppData\DongDong\Download\file\2023-04\BaseDataPriceDetail.csv",sep=',',usecols=[4])arrary=data.values[0::,0::]#读取全部行,全部列print(arrary[19])输出......
  • [Python自动化]使用Python Pexpect模块实现自动化交互脚本使用心得
    使用PythonPexpect模块实现自动化交互脚本使用心得参考文档:https://pexpect.readthedocs.io/en/stable/前言在最近的工作中,需要使用DockerFile构建镜像。在构建镜像的过程中,有一些执行的命令是需要交互的。例如安装tzdata(aptinstalltzdata),不过在使用apt安装时,可以直接使......