美文网首页python3 运维开发
Python3 函数的更高级的话题(二)

Python3 函数的更高级的话题(二)

作者: 运维开发_西瓜甜 | 来源:发表于2018-11-25 17:12 被阅读22次

1. 利用闭包去替换简单的类

有的时候,你定义了一个类,但是这个类除了 __init__() 方法外,只有一个方法。
这样的话,定义一个类显得有点不够优雅了,首先类肯定比函数要占用更多的内存,并且也复杂。

下面看我是如何用闭包优雅且简洁的解决这样的问题的。

首先假设你定义了一个这样的类:

class ShowInfo:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show_format(self, template):
        print(template.format_map(vars(self)))

obj = ShowInfo('a', 1)

tpl = """姓名: {name}
年龄: {age}
"""

obj.show_format(tpl)

# 以下是打印出来的结果
"""
姓名:shark
年龄:18
"""

这个类是很无聊的,就是把对象的属性按照用户输入的格式,打印出来。随然整个类没什么卵用,但是足可以说明我们要阐述的内容。

以上的类可以使用闭包来优雅的实现:

def show_info(name, age):
    name=name
    age = age
    info = locals()

    def show_format(template):
        print(template.format_map(info))
    return show_format

show = show_info('shark', 18)

tpl = """姓名: {name}
年龄: {age}
"""
show(tpl)

2. 回调函数

假设你写了一个函数需要用到调函数,原因可能是执行了异步操作,或者在一些框架中会要求有回调函数。

如下:

def apply_async(func, args, *, callback):
    # 计算结果
    result = func(*args)

    # 接着在这个函数内部打印计算的结果
    callback(result)

# 用于计算的函数
def add(x, y):
    return x + y

# 回调函数
def print_result(result):
    print('Got:', result)

# 使用
apply_async(add, (3, 5), callback=print_result)

# Got: 8

看起来上面的代码都很美好,但是假如回调函数想用到额外的变量,就会很麻烦,因为我们这里把回调函数的参数写死了,只能接收一个参数。

解决办法: 可以用闭包来实现。
比如下面的闭包,就是在闭包中使用一个变量来记录总共处理了多少个结果了。

下面的函数实现的功能就是,保存一个内部序列号,每次接收到一个 result 的时候序列号 加 1

def make_handler():
    sequence = 0
    def handler(result):
        # 声明一下这个不是此函数的本地变量,就是改变作用域的关系
        nonlocal sequence
        sequence += 1
        print('[{}] Got: {}'.format(sequence, result))
    return handler
    
# 获取到回调函数
handler = make_handler()

# 使用这个回调函数
apply_async(add, ('hello', 'world'), callback=handler)  # [1] Got: helloworld
apply_async(add, ('hello', 'world'), callback=handler)  # [2] Got: helloworld

更高级的办法是使用协程

def make_handler():
    sequence = 0
    while True:
        # 使用 yield 关键字来实现协程
        result = yield
        sequence += 1
        print('[{}] Got: {}'.format(sequence, result))

使用的时候就需要用协程的 send() 方法了。

handler = make_handler()

r = next(handler)  # 先释放 yield 的返回值
apply_async(add, (3, 8), callback=handler.send)
apply_async(add, ('hello', 'world'), callback=handler.send)

你可以看到输出的效果是一样的。

相关文章

  • Python3 函数的更高级的话题(二)

    1. 利用闭包去替换简单的类 有的时候,你定义了一个类,但是这个类除了 __init__() 方法外,只有一个方法...

  • 函数的高级话题

    处理任意结构:type 比较 istance函数 前者不能处理subclass lambad函数(实现函数速写,用...

  • Python3 函数的更高级的话题(一)

    本次我要给大家分享一些更加高级和不常见的函数定义与使用模式。 涉及到的内容包括默认参数、任意数量参数、强制关键字 ...

  • Python入门

    Python3教程 安装Python 第一个Python程序 Python基础 函数 高级特性 函数式编程 模块 ...

  • 2018-01-30Python二、函数笔记

    !/usr/bin/env python3 -*- coding:utf-8 -*- 二、函数 1.调用函数 ''...

  • python3 range() 函数和 xrange() 函数

    python3 range 函数 python3 取消了 xrange() 函数,并且和 range() 函数合并...

  • 第19章 函数的高级话题

    lambda表达式和def语句有什么关系?两者都可以声称函数,lambda是简易的函数表达式,用于逻辑简单的场合,...

  • python3函数(一)

    python3中可以调用函数和定义函数。 1、调用函数 直接调用python3自带的函数 (1)函数abs(-10...

  • day2-python3函数

    今天练习了python3的各类型函数。包括: 基本语法 高级函数 递归 生成器与迭代器 闭包与装饰器 练习题代码实...

  • 第十九章、函数的高级话题

    这一章将会介绍一系列更高级的与函数相关的话题:递归函数、函数属性和注解、lambda表达式、如map和filter...

网友评论

    本文标题:Python3 函数的更高级的话题(二)

    本文链接:https://www.haomeiwen.com/subject/sznpqqtx.html