设为首页 加入收藏

TOP

Python核心技术与实战 笔记(三)
2019-09-20 11:45:42 】 浏览:168
Tags:Python 核心 技术 实战 笔记
print(message) greet('hello world') # 输出 wrapper of decorator hello world

带自定义参数的装饰器

def repeat(num):
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(num):
                print('wrapper of decorator')
                func(*args, **kwargs)
        return wrapper
    return my_decorator


@repeat(4)
def greet(message):
    print(message)

greet('hello world')

# 输出:
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world

上述 green() 函数被装饰以后,它的元信息会发生改变,可勇敢 greet__name__ 来查看。可通过内置装饰器来解决这个问题

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('wrapper of decorator')
        func(*args, **kwargs)
    return wrapper
    
@my_decorator
def greet(message):
    print(message)

greet.__name__

# 输出
'greet'

类装饰器

class Count:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print('num of calls is: {}'.format(self.num_calls))
        return self.func(*args, **kwargs)

@Count
def example():
    print("hello world")

example()

# 输出
num of calls is: 1
hello world

example()

# 输出
num of calls is: 2
hello world

装饰器支持嵌套使用

@decorator1
@decorator2
@decorator3
def func():
    ...

# 等价于
decorator1(decorator2(decorator3(func)))

装饰器使用场景:

  • 身份认证
  • 日志记录
  • 输入合理性检查
  • 缓存(LRU cache)

metaclass

metaclass 是 Python 黑魔法级别的语言特性,它可以改变正常 Python 类型的创建过程。

  • 所有 Python 的用户定义类,都是 type 这个类的实例
  • 用户自定义类,只不过是 type 类的 __ call __ 运算符重载
  • metaclass 是 type 的子类,通过替换 type 的 __ call __ 运算符重载机制,超越变形正常的类
class Mymeta(type):
    def __init__(self, name, bases, dic):
        super().__init__(name, bases, dic)
        print('===>Mymeta.__init__')
        print(self.__name__)
        print(dic)
        print(self.yaml_tag)

    def __new__(cls, *args, **kwargs):
        print('===>Mymeta.__new__')
        print(cls.__name__)
        return type.__new__(cls, *args, **kwargs)

    def __call__(cls, *args, **kwargs):
        print('===>Mymeta.__call__')
        obj = cls.__new__(cls)
        cls.__init__(cls, *args, **kwargs)
        return obj
    
class Foo(metaclass=Mymeta):
    yaml_tag = '!Foo'

    def __init__(self, name):
        print('Foo.__init__')
        self.name = name
 
    def __new__(cls, *args, **kwargs):
        print('Foo.__new__')
        return object.__new__(cls)

foo = Foo('foo')

迭代器和生成器

  • 容器时可迭代对象,可迭代对象调用 iter() 函数,可以得到一个迭代器。迭代器可以通过 next() 函数来得到下一个元素,从而支持遍历
  • 生成器时一种特殊的迭代器,合理使用生成器,可以降低内存占用、优化程序结构、提高程序速度
  • 生成器在 Python 2 的版本上,是协程的一种重要实现方式;而 Python 3.5 引入的 async、await 语法糖,生成器实现协程的方式就已经落后了。

协程

协程是实现并发编程的一种方式

  • 协程和多线程的区别,主要在于两点,一是协程为单线程;二是协程由用户决定,在哪些地方交出控制权,切换到下一个任务
  • 协程的写法更加简洁清晰;把 async/await 语法和 create_task 结合起来用,对于中小级别的并发需求已经毫无压力

生产者/消费者 模型

import asyncio
import random

async def consumer(queue, id):
    while True:
        val = await queue.get()
        print('{} get a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def producer(queue, id):
    for i in range(5):
        val = random.randint(1, 10)
        await queue.put(val)
        print('{} put a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def main():
    queue = asyncio.Queue()

    consumer_1 = asyncio.create_task(consumer(queue, 'consumer_1'))
    consumer_2 = asyncio.create_task(consumer(queue, 'consumer_2'))

    producer_1 = asyncio.create_task(producer(queue, 'producer_1'))
    producer_2 = asyncio.create_task(producer(queue, 'producer_2'))

    await asyncio.sleep(10)
    consumer_1.can
首页 上一页 1 2 3 4 5 6 下一页 尾页 3/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇构建支持中文字体的moviepy镜像 下一篇django下创建多个app,如何设置每..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目