装饰器函数 包装函数 包裹函数

 

import re
import traceback
from itertools import chain
from functools import partial
from timeit import default_timer as timer

from .decorators import decorator, wraps, Call


__all__ = [
'tap',
'log_calls', 'print_calls',
'log_enters', 'print_enters',
'log_exits', 'print_exits',
'log_errors', 'print_errors',
'log_durations', 'print_durations',
'log_iter_durations', 'print_iter_durations',
]

REPR_LEN = 25


def tap(x, label=None):
"""Prints x and then returns it."""
if label:
print('%s: %s' % (label, x))
else:
print(x)
return x


@decorator
def log_calls(call, print_func, errors=True, stack=True, repr_len=REPR_LEN):
"""Logs or prints all function calls,
including arguments, results and raised exceptions."""
signature = signature_repr(call, repr_len)
try:
print_func('Call %s' % signature)
result = call()
# NOTE: using full repr of result
print_func('-> %s from %s' % (smart_repr(result, max_len=None), signature))
return result
except BaseException as e:
if errors:
print_func('-> ' + _format_error(signature, e, stack))
raise

def print_calls(errors=True, stack=True, repr_len=REPR_LEN):
if callable(errors):
return log_calls(print)(errors)
else:
return log_calls(print, errors, stack, repr_len)
print_calls.__doc__ = log_calls.__doc__


@decorator
def log_enters(call, print_func, repr_len=REPR_LEN):
"""Logs each entrance to a function."""
print_func('Call %s' % signature_repr(call, repr_len))
return call()


def print_enters(repr_len=REPR_LEN):
"""Prints on each entrance to a function."""
if callable(repr_len):
return log_enters(print)(repr_len)
else:
return log_enters(print, repr_len)


@decorator
def log_exits(call, print_func, errors=True, stack=True, repr_len=REPR_LEN):
"""Logs exits from a function."""
signature = signature_repr(call, repr_len)
try:
result = call()
# NOTE: using full repr of result
print_func('-> %s from %s' % (smart_repr(result, max_len=None), signature))
return result
except BaseException as e:
if errors:
print_func('-> ' + _format_error(signature, e, stack))
raise

def print_exits(errors=True, stack=True, repr_len=REPR_LEN):
"""Prints on exits from a function."""
if callable(errors):
return log_exits(print)(errors)
else:
return log_exits(print, errors, stack, repr_len)


class LabeledContextDecorator(object):
"""
A context manager which also works as decorator, passing call signature as its label.
"""
def __init__(self, print_func, label=None, repr_len=REPR_LEN):
self.print_func = print_func
self.label = label
self.repr_len = repr_len

def __call__(self, label=None, **kwargs):
if callable(label):
return self.decorator(label)
else:
return self.__class__(self.print_func, label, **kwargs)

def decorator(self, func):
@wraps(func)
def inner(*args, **kwargs):
# Recreate self with a new label so that nested and recursive calls will work
cm = self.__class__.__new__(self.__class__)
cm.__dict__.update(self.__dict__)
cm.label = signature_repr(Call(func, args, kwargs), self.repr_len)
with cm:
return func(*args, **kwargs)
return inner


class log_errors(LabeledContextDecorator):
"""Logs or prints all errors within a function or block."""
def __init__(self, print_func, label=None, stack=True, repr_len=REPR_LEN):
LabeledContextDecorator.__init__(self, print_func, label=label, repr_len=repr_len)
self.stack = stack

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, tb):
if exc_type:
if self.stack:
exc_message = ''.join(traceback.format_exception(exc_type, exc_value, tb))
else:
exc_message = '%s: %s' % (exc_type.__name__, exc_value)
self.print_func(_format_error(self.label, exc_message, self.stack))

print_errors = log_errors(print)


# Duration utils

def format_time(sec):
if sec < 1e-6:
return '%8.2f ns' % (sec * 1e9)
elif sec < 1e-3:
return '%8.2f mks' % (sec * 1e6)
elif sec < 1:
return '%8.2f ms' % (sec * 1e3)
else:
return '%8.2f s' % sec

time_formatters = {
'auto': format_time,
'ns': lambda sec: '%8.2f ns' % (sec * 1e9),
'mks': lambda sec: '%8.2f mks' % (sec * 1e6),
'ms': lambda sec: '%8.2f ms' % (sec * 1e3),
's': lambda sec: '%8.2f s' % sec,
}


class log_durations(LabeledContextDecorator):
"""Times each function call or block execution."""
def __init__(self, print_func, label=None, unit='auto', threshold=-1, repr_len=REPR_LEN):
LabeledContextDecorator.__init__(self, print_func, label=label, repr_len=repr_len)
if unit not in time_formatters:
raise ValueError('Unknown time unit: %s. It should be ns, mks, ms, s or auto.' % unit)
self.format_time = time_formatters[unit]
self.threshold = threshold

def __enter__(self):
self.start = timer()
return self

def __exit__(self, *exc):
duration = timer() - self.start
if duration >= self.threshold:
duration_str = self.format_time(duration)
self.print_func("%s in %s" % (duration_str, self.label) if self.label else duration_str)

print_durations = log_durations(print)


def log_iter_durations(seq, print_func, label=None, unit='auto'):
"""Times processing of each item in seq."""
if unit not in time_formatters:
raise ValueError('Unknown time unit: %s. It should be ns, mks, ms, s or auto.' % unit)
_format_time = time_formatters[unit]
suffix = " of %s" % label if label else ""
it = iter(seq)
for i, item in enumerate(it):
start = timer()
yield item
duration = _format_time(timer() - start)
print_func("%s in iteration %d%s" % (duration, i, suffix))

def print_iter_durations(seq, label=None, unit='auto'):
"""Times processing of each item in seq."""
return log_iter_durations(seq, print, label, unit=unit)


### Formatting utils

def _format_error(label, e, stack=True):
if isinstance(e, Exception):
if stack:
e_message = traceback.format_exc()
else:
e_message = '%s: %s' % (e.__class__.__name__, e)
else:
e_message = e

if label:
template = '%s raised in %s' if stack else '%s raised in %s'
return template % (e_message, label)
else:
return e_message


### Call signature stringification utils

def signature_repr(call, repr_len=REPR_LEN):
if isinstance(call._func, partial):
if hasattr(call._func.func, '__name__'):
name = '<%s partial>' % call._func.func.__name__
else:
name = '<unknown partial>'
else:
name = getattr(call._func, '__name__', '<unknown>')
args_repr = (smart_repr(arg, repr_len) for arg in call._args)
kwargs_repr = ('%s=%s' % (key, smart_repr(value, repr_len))
for key, value in call._kwargs.items())
return '%s(%s)' % (name, ', '.join(chain(args_repr, kwargs_repr)))

def smart_repr(value, max_len=REPR_LEN):
if isinstance(value, (bytes, str)):
res = repr(value)
else:
res = str(value)

res = re.sub(r'\s+', ' ', res)
if max_len and len(res) > max_len:
res = res[:max_len-3] + '...'
return res



Overview — funcy 2.0 documentation https://funcy.readthedocs.io/en/stable/overview.html

 

 

术语对照表 — Python 3.13.0a0 文档 https://docs.python.org/zh-cn/dev/glossary.html#term-decorator

decorator -- 装饰器

返回值为另一个函数的函数,通常使用 @wrapper 语法形式来进行函数变换。 装饰器的常见例子包括 classmethod() 和 staticmethod()

装饰器语法只是一种语法糖,以下两个函数定义在语义上完全等价:

def f(arg):
    ...
f = staticmethod(f)

@staticmethod
def f(arg):
    ...

同样的概念也适用于类,但通常较少这样使用。有关装饰器的详情可参见 函数定义 和 类定义 的文档。

descriptor -- 描述器

任何定义了 __get__()__set__() 或 __delete__() 方法的对象。当一个类属性为描述器时,它的特殊绑定行为就会在属性查找时被触发。通常情况下,使用 a.b 来获取、设置或删除一个属性时会在 a 的类字典中查找名称为 b 的对象,但如果 b 是一个描述器,则会调用对应的描述器方法。理解描述器的概念是更深层次理解 Python 的关键,因为这是许多重要特性的基础,包括函数、方法、属性、类方法、静态方法以及对超类的引用等等。

有关描述器的方法的更多信息,请参阅 实现描述器 或 描述器使用指南

 

 

【some code will be added on the top of decorated function---Beta Words---被装饰的函数头部会被添加一些新代码且先被执行】

https://hackernoon.com/decorators-in-python-8fd0dce93c08

def decorator_func(say_hello_func):
    def wrapper_func(hello_var, world_var):
        hello,world = "Hello, ","World"

        if not hello_var:
            hello_var = hello

        if not world_var:
            world_var = world

        return say_hello_func(hello_var, world_var)

    return wrapper_func


@decorator_func
def say_hello(hello_var, world_var):
    print(hello_var + " " + world_var)


say_hello("Hello", "")

  

https://zh.wikipedia.org/wiki/包裝函式

https://en.wikipedia.org/wiki/Wrapper_function

 

计算机科学中,包装函数英语:Wrapper function)是一种计算机程序中的函数,它存在的主要目的就是用来调用另一个函数。在面向对象编程中,它又被称为方法委任(method delegation)。它的存在有多种功能:可以被当成适配器模式来使用,可以当成错误检查程序,也可以被当成多重继承来使用。

public class StackSet implements Stack, Set {

    private LinkedList stack;
    private HashSet set;

    public boolean push(Object o) {
        if (set.add(o)) return stack.push(o);
        else return false;
    }

    public Object pop() {
        Object o = stack.pop();
        set.remove(o);
        return o;
    }

    public boolean contains(Object o) {
        return set.contains(o);
    }

}

 

wrapper function is a subroutine in a software library or a computer program whose main purpose is to call a second subroutine[1] or a system call with little or no additional computation. Wrapper functions are used to make writing computer programs easier by abstracting away the details of a subroutine's underlying implementation.

rapper functions are a means of delegation and can be used for a number of purposes.

Programming convenience

Wrapper functions can be used to make writing computer programs easier. An example of this is the MouseAdapter and similar classes in the Java AWT library.[2] Wrapper functions are useful in the development of applications that use third-party library functions. A wrapper can be written for each of the third party functions and used in the native application. In case the third party functions change or are updated, only the wrappers in the native application need to be modified as opposed to changing all instances of third party functions in the native application.

Adapting class/object interfaces

Wrapper functions can be used to adapt an existing class or object to have a different interface. This is especially useful when using existing library code.

Code testing

Wrapper functions can be used to write error checking routines for pre-existing system functions without increasing the length of a code by a large amount by repeating the same error check for each call to the function.[3] All calls to the original function can be replaced with calls to the wrapper, allowing the programmer to forget about error checking once the wrapper is written. A test driver is a kind of wrapper function that exercises a code module, typically calling it repeatedly, with different settings or parameters, in order to rigorously pursue each possible path. It is not deliverable code, but is not throwaway code either, being typically retained for use in regression testing. An interface adaptor is a kind of wrapper function that simplifies, tailors, or amplifies the interface to a code module, with the intent of making it more intelligible or relevant to the user. It may rename parameters, combine parameters, set defaults for parameters, and the like.

Multiple inheritance

In a programming language that does not support multiple inheritance of base classes, wrapper functions can be used to simulate it. Below is an example of part of a Java class that "inherits" from LinkedList and HashSet. See Method for further implementation details.

public class Test implements LinkedList, HashSet{

@Override
//contains data members and data methods
//covariant return

}

Library functions and system calls

Many library functions, such as those in the C Standard Library, act as interfaces for abstraction of system calls. The fork and execve functions in glibc are examples of this. They call the lower-level fork and execve system calls, respectively.

This may lead to incorrectly using the terms "system call" and "syscall" to refer to higher-level library calls rather than the similarly named system calls, which they wrap.[citation needed]

 

 

def my_decorator(f):
    from functools import wraps
    @wraps(f)
    def wrapper(*args, **kwargs):
        print('1')
        print(args)
        print(kwargs)
        return f(*args, **kwargs)

    return wrapper


@my_decorator
def ex(*args, **kwargs):
    print('2----->')


ex(11, 22, d=33, e=44)

# 需求
# 在Django控制台打印接口调用方的请求参数

  

1
(11, 22)
{'d': 33, 'e': 44}
2----->

  

def my_decorator(f):
    from functools import wraps
    @wraps(f)
    def wrapper(*args, **kwargs):
        print('1')
        print(args)
        print(kwargs)
        # return f(*args, **kwargs)
        return f(args, kwargs)

    return wrapper


@my_decorator
def ex(*args, **kwargs):
    print('2----->')


ex(11, 22, d=335, e=44)

 

1
(11, 22)
{'d': 335, 'e': 44}
2----->

 

 

 

  

 

 

 

 

 https://en.wikipedia.org/wiki/Wrapper_function


Library functions and system calls

Many library functions, such as those in the C Standard Library, act as interfaces for abstraction of system calls. The fork and execve functions in glibc are examples of this. They call the lower-level fork and execve system calls, respectively.

This may lead to incorrectly using the terms "system call" and "syscall" to refer to higher-level library calls rather than the similarly named system calls, which they wrap.[citation needed]

 

 

装饰器 - 廖雪峰的官方网站 https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584

 

装饰器

 

 

 

 

 

 

 







posted @ 2017-06-08 22:43  papering  阅读(445)  评论(0编辑  收藏  举报