函数装饰器和闭包(四)

上一章:函数装饰器和闭包(三)

单分派函数

假设我们现在要开发一个函数,这个函数可以传入一个元素,函数要判断元素的类型,再将其打印出来

from collections.abc import MutableSequence, MutableMapping

def print_item(item):
    if isinstance(item, int):
        print("int:", item)
    elif isinstance(item, MutableSequence):
        print("iter:", item)
    elif isinstance(item, MutableMapping):
        print("map:", item)
    else:
        print(item)

  

运行结果:

>>> print_item(1)
int: 1
>>> print_item([1, 2, 3])
sequence: [1, 2, 3]
>>> print_item({"a": 1, "b": 2})
map: {‘a‘: 1, ‘b‘: 2}

  

这个函数很好理解,没有什么好解释的,但是我们要通过这个函数来展示如何使用functools.singledispatch装饰器让Python实现“重载”的效果

from collections.abc import MutableSequence, MutableMapping
from functools import singledispatch

@singledispatch  # <1>
def print_item(item):
    print(item)

@print_item.register(int)  # <2>
@print_item.register(float)
def _(item):
    print("number:", item)

@print_item.register(str)  # <3>
def _(item):
    print("str:", item)

@print_item.register(MutableSequence)  # <4>
def _(item):
    print("sequence:", item)

@print_item.register(MutableMapping)  # <5>
def _(item):
    print("map:", item)

     

我们用@singledispatch装饰了print_item函数,把这个函数作为基函数,然后再用@print_item.register装饰其他函数,当我们调用print_item,会根据item的类型查找应该执行的函数

  1. @singledispatch标记处理object类型的基函数
  2. 当传入参数为int类型进入此方法,这个时候专门的函数名称已经无关紧要了,我们用_代替,同时可以用多个@print_item.register装饰同一个函数
  3. 当传入参数为str类型进入此方法
  4. 当传入参数为序列类型进入此方法
  5. 当传入参数为字典类型进入此方法

  

运行结果:

>>> print_item(1)
number: 1
>>> print_item(1.1)
number: 1.1
>>> print_item("hello")
str: hello
>>> print_item([1, 2, 3])
sequence: [1, 2, 3]
>>> print_item({"a": 1, "b": 2})
map: {‘a‘: 1, ‘b‘: 2}

参数化装饰器

Python在解释装饰器时,把被装饰的函数当做第一个参数传递给装饰器函数,但怎么样才能让装饰器接收其他参数呢?答案是:创建一个装饰器工厂函数,把参数传给它,返回一个装饰器,然后再把它应用到要装饰的函数上。可能这样的解释听得云里雾里,没关系,我们来看下面一个例子

registry = set()  # <1>

def register(active=True):  # <2>
    def decorate(func):  # <3>
        print(‘running register(active=%s)->decorate(%s)‘ % (active, func))
        if active:  # <4>
            registry.add(func)
        else:
            registry.discard(func)  # <5>

        return func  # <6>

    return decorate  # <7>

@register(active=False)  # <8>
def f1():
    print(‘running f1()‘)

@register()  # <9>
def f2():
    print(‘running f2()‘)

def f3():
    print(‘running f3()‘)

  

  1. 声明一个名为registry的集合对象
  2. register方法接收一个可选的关键字参数
  3. decorate这个内部函数才是真正的装饰器,注意它只有一个参数,而且接收的是函数
  4. 只有active的值为真,才将func注册到registry集合中
  5. 如果active的值不为真,则将func从registry集合删除
  6. decorate是装饰器,必须返回一个函数
  7. register是装饰器工厂函数,因此返回decorate
  8. @register工厂函数必须作为函数调用,并且传入所需的参数
  9. 即时不传入参数,register也必须作为函数调用

我们导入这个文件:

>>> from registration_param import *
running register(active=False)->decorate(<function f1 at 0x00000072D8DA4620>)
running register(active=True)->decorate(<function f2 at 0x00000072D8DA46A8>)
>>> registry
{<function f2 at 0x00000072D8DA46A8>}

  

可以看到,当把register作为装饰器工厂函数,返回的decorate函数得到了执行,由于f1传入的active为False,所以f1没有注册到registry集合对象里面,只有f2被注册到集合对象,我们打印registry,可以看到,里面确实只有f2函数对象

原文地址:https://www.cnblogs.com/beiluowuzheng/p/9310005.html

时间: 2024-08-28 05:07:44

函数装饰器和闭包(四)的相关文章

函数装饰器和闭包(一)

装饰器基础知识 装饰器是可调用的对象,其参数是另一个函数(被装饰的函数),装饰器可能会处理被装饰的函数,然后将它返回,或者将其替换成另一个函数或可调用对象 def deco(func): def inner(): print("running innner()") return inner # <1> @deco def target(): # <2> print("running target()") target() # <3>

Python 函数装饰器和闭包

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 25.0px Helvetica } 装饰器基础知识 装饰器是可调用的对象,其参数是另一个函数(被装饰的函数). 装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Helvetica } 假如有个名为 decorate 的装饰器: @decorate def targ

Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数

一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(First-Class Object)呢? 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的. 1.函数身为一个对象,拥有对象模型的三个通用属性:id.类型.和值.

【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】

一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(First-Class Object)呢? 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的. 1.函数身为一个对象,拥有对象模型的三个通用属性:id.类型.和值.

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

python函数下篇装饰器和闭包,外加作用域

装饰器和闭包的基础概念 装饰器是一种设计模式能实现代码重用,经常用于查日志,性能测试,事务处理等,抽离函数大量不必的功能. 装饰器:1.装饰器本身是一个函数,用于装饰其它函数:2.功能:增强被装饰函数的功能. 装饰器需要遵循的原则 1.不修改被装饰函数的源代码(开放封闭原则) 2.为被装饰函数添加新功能后,不修改被装饰函数的调用方式 装饰器 = 高阶函数+函数嵌套+闭包 高阶函数 1.函数接受的参数是一个函数名 2.函数的返回值是一个函数名 3.只有上述条件满足一个就是高阶函数 def foo(

Python高阶函数与函数装饰器-day4

上节回顾 高阶函数 闭包函数 函数装饰器 模块导入 一.上节回顾 Python2与Python3字符编码问题,不管你是初学者还是已经对Python的项目了如指掌了,都会犯一些编码上面的错误.我在这里简单归纳Python3和Python2各自的区别. 首先是Python3-->代码文件都是用utf-8来解释的.将代码和文件读到内存中就变成了Unicode,这也就是为什么Python只有encode没有decode了,因为内存中都将字符编码变成了Unicode,而Unicode是万国码,可以"

python函数装饰器

学习装饰器前提需要了解高阶函数,函数嵌套,函数闭包 python函数装饰器,顾名思义就是装饰函数,为函数添加新功能的的一种方式. 为什么要使用装饰器呢? 因为函数在运行时,如果不使用装饰器对函数进行功能添加,需要修改函数源代码,这样修改无疑会增加程序的冗余和复杂性,也不便于程序员对其进行修改.使用装饰器,可以在不改变函数源代码和调用方式的前提下,使用语法糖@装饰器,对函数功能进行添加. 装饰器本质上就是一个函数. 我们使用一个简单的例子来实现: import time #这是一个装饰器函数名为t

Python 函数装饰器入门

原文链接: --> A guide to Python's function decorators Python功能强劲,语法表现力强,尤其装饰器深深的吸引着我.在设计模式中,装饰器可以在不使用子类的情况下,动态的改变函数,方法以及类的功能.这个功能非常有用,特别在你想扩展函数的功能同时又不想改变原有的函数.的确,我们任意的实现装饰器设计模式,但是,python通过提供简单的语法和特性让装饰器的实现变的如此简单. 在本文中,我将用一组例子来深入浅入python 函数装饰器的功能,所有的例子都是在