• Python--进阶处理9


    # =========================第九章:元编程=============================

    # ----------------在函数上添加包装器-----------------------
    # 在函数上添加一个包装器,增加额外的操作处理(比如日志、计时等)
    import time
    from functools import wraps

    def timethis(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    start = time.time()
    result = func(*args, **kwargs)
    end = time.time()
    print(func.__name__, end - start)
    return result
    return wrapper

    @timethis
    def countdown(n):
    while n > 0:
    n -= 1

    countdown(10000000)
    # 一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数
    # 任何时候定义装饰器的时候,都应该使用functools 库中的@wraps 装饰器来注解底层包装函数
    # 在编写装饰器的时候复制元信息是一个非常重要的部分。如果你忘记了使用@wraps,那么你会发现被装饰函数丢失了所有有用的信息

    from functools import wraps
    import logging

    def logged(level, name=None, meaasge=None):
    def decorate(func):
    logname = name if name else func.__module__
    log = logging.getLogger(logname)
    logmsg = meaasge if meaasge else func.__name__

    @wraps(func)
    def wrapper(*args, **kwargs):
    log.log(level, logmsg)
    return func(*args, **kwargs)
    return wrapper
    return decorate

    @logged(logging.DEBUG)
    def add(x, y):
    return x + y

    """
    最外层的函数logged()接受参数并将它们作用在内部的装饰器函数上面。
    内层的函数decorate() 接受一个函数作为参数,
    然后在函数上面放置一个包装器。
    这里的关键点是包装器是可以使用传递给logged() 的参数的
    """

    from inspect import signature
    from functools import wraps

    def typeassert(*ty_args, **ty_kwargs):
    def decorate(func):
    if not __debug__:
    return func

    sig = signature(func)
    bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments

    @wraps(func)
    def wrapper(*args, **kwargs):
    bound_values = sig.bind(*args, **kwargs)
    for name, value in bound_values.arguments.items():
    if name in bound_types:
    if not isinstance(value, bound_types[name]):
    raise TypeError('Argument {} must be {}'.format(name, bound_types[name]))
    return func(*args, **kwargs)
    return wrapper
    return decorate
    """
    可以看出这个装饰器非常灵活,既可以指定所有参数类型,也可以只指定部分。
    并且可以通过位置或关键字来指定参数类型
    """
    @typeassert(int, z=int)
    def spam(x, y, z=24):
    print(x, y, z)

    spam(1, 2, 3)
    spam(1, '2', 3)
    # spam(1, 'a', 'b')
    # ----------------------------------------------------------------------------------------------

    # ------------------将装饰器定义为类的一部分--------------------------------
    from functools import wraps

    class A:
    # Decorator as an instance method
    def decorator1(self, func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    print('Decorator 1')
    return func(*args, **kwargs)
    return wrapper

    # Decorator as a class method
    @classmethod
    def decorator2(cls, func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    print('Decorator 2')
    return func(*args, **kwargs)
    return wrapper
    # 一个是实例调用,一个是类调用
    a = A()
    @a.decorator1
    def spam():
    pass

    @A.decorator2
    def grok():
    pass
    # -----------------------------------------------------------------------

    # 将装饰器定义为类
    # 为了将装饰器定义成一个实例,你需要确保它实现了__call__() 和__get__() 方法
    import types
    from functools import wraps

    class Profiled:
    def __init__(self, func):
    wraps(func)(self)
    self.ncalls = 0

    def __call__(self, *args, **kwargs):
    self.ncalls += 1
    return self.__wrapped__(*args, **kwargs)

    def __get__(self, instance, cls):
    if instance is None:
    return self
    else:
    return types.MethodType(self, instance)

    @Profiled
    def add(x, y):
    return x + y

    class Spam:
    @Profiled
    def bar(self, x):
    print(self, x)
    # --------------------------------------------------------------------------------
    # ?????????????????????????????332
  • 相关阅读:
    网络中有三种通讯模式:单播、广播、组播(多播)
    chmod命令
    linux bash 命令重定向和多命令执行
    linux中管道符“|”的作用
    web测试常用的 linux 命令
    集群主要分成三大类 (高可用集群, 负载均衡集群,科学计算集群)
    iOS 监测电话呼入
    iOS NSUserDefaults [setValue:forKey:] [setObject:forKey:] <Objc> setValue(_,forKey:) set(_,forKey) <Swift 3>
    iOS 将navigationItem.titleView设置为自定义UISearchBar (Ficow实例讲解)
    iOS 加载Viewcontroller的几种方法
  • 原文地址:https://www.cnblogs.com/fqfanqi/p/8446504.html
Copyright © 2020-2023  润新知