effective python 42.用functools.wraps定义函数装饰器

根据开放封闭原则,选择装饰器模式,A像B,但A还不够像B

def foo():
    """
    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    """
    print('GoodGoodStudy,DayDayUp in foo')


foo()
print(foo.__doc__)
print('-------------------------------------')


def bar(func):
    def wrapper(*args, **kwargs):
        print('GoodGoodStudy,DayDayUp in bar')
        return func(*args, **kwargs)
    return wrapper


@bar
def foo():
    """
    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    """
    print('GoodGoodStudy,DayDayUp in foo')


foo()
print(foo.__doc__)

输出结果:

GoodGoodStudy,DayDayUp in foo

    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    
-------------------------------------
GoodGoodStudy,DayDayUp in bar
GoodGoodStudy,DayDayUp in foo
None

为了更像,用上functools中的wraps(被装饰的函数)

from functools import wraps


def far():
    """
    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    """
    print('GoodGoodStudy,DayDayUp in far')


far()
print(far.__doc__)
print('-------------------------------------')


def boo(func):
    def wrapper(*args, **kwargs):
        print('GoodGoodStudy,DayDayUp in boo')
        return func(*args, **kwargs)
    return wrapper


@boo
def far():
    """
    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    """
    print('GoodGoodStudy,DayDayUp in far')


far()
print(far.__doc__)
print('-------------------------------------')


def boo1(func):

    @wraps(func)
    def wrapper(*args, **kwargs):
        print('GoodGoodStudy,DayDayUp in boo')
        return func(*args, **kwargs)
    return wrapper


@boo1
def far():
    """
    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    """
    print('GoodGoodStudy,DayDayUp in far')


far()
print(dir(boo))
GoodGoodStudy,DayDayUp in foo

    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU
    
-------------------------------------
GoodGoodStudy,DayDayUp in bar
GoodGoodStudy,DayDayUp in foo
None
-------------------------------------
GoodGoodStudy,DayDayUp in bar
GoodGoodStudy,DayDayUp in foo

    Δ~~~~Δ
    ξ •ェ• ξ
    ξ ~ ξ
    ξ   ξ
    ξ   “~~~~〇
    ξ       ξ
    ξ ξ ξ~~~ξ ξ
     ξ_ξξ_ξ ξ_ξξ_ξ
      ヽ(´•ω•)ノ
        |  /
        UU

在这里插入图片描述在这里插入图片描述
getattr在这里插入图片描述

PyObject *
    _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name,
                                     PyObject *dict, int suppress)
    {
        /* Make sure the logic of _PyObject_GetMethod is in sync with
           this method.
    
           When suppress=1, this function suppress AttributeError.
        */
    
        PyTypeObject *tp = Py_TYPE(obj);
        PyObject *descr = NULL;
        PyObject *res = NULL;
        descrgetfunc f;
        Py_ssize_t dictoffset;
        PyObject **dictptr;
    
        if (!PyUnicode_Check(name)){
            PyErr_Format(PyExc_TypeError,
                         "attribute name must be string, not '%.200s'",
                         name->ob_type->tp_name);
            return NULL;
        }
        Py_INCREF(name);
    
        if (tp->tp_dict == NULL) {
            if (PyType_Ready(tp) < 0)
                goto done;
        }
    
        descr = _PyType_Lookup(tp, name);
    
        f = NULL;
        if (descr != NULL) {
            Py_INCREF(descr);
            f = descr->ob_type->tp_descr_get;
            if (f != NULL && PyDescr_IsData(descr)) {
                res = f(descr, obj, (PyObject *)obj->ob_type);
                if (res == NULL && suppress &&
                        PyErr_ExceptionMatches(PyExc_AttributeError)) {
                    PyErr_Clear();
                }
                goto done;
            }
        }
    
        if (dict == NULL) {
            /* Inline _PyObject_GetDictPtr */
            dictoffset = tp->tp_dictoffset;
            if (dictoffset != 0) {
                if (dictoffset < 0) {
                    Py_ssize_t tsize;
                    size_t size;
    
                    tsize = ((PyVarObject *)obj)->ob_size;
                    if (tsize < 0)
                        tsize = -tsize;
                    size = _PyObject_VAR_SIZE(tp, tsize);
                    assert(size <= PY_SSIZE_T_MAX);
    
                    dictoffset += (Py_ssize_t)size;
                    assert(dictoffset > 0);
                    assert(dictoffset % SIZEOF_VOID_P == 0);
                }
                dictptr = (PyObject **) ((char *)obj + dictoffset);
                dict = *dictptr;
            }
        }
        if (dict != NULL) {
            Py_INCREF(dict);
            res = PyDict_GetItem(dict, name);
            if (res != NULL) {
                Py_INCREF(res);
                Py_DECREF(dict);
                goto done;
            }
            Py_DECREF(dict);
        }
    
        if (f != NULL) {
            res = f(descr, obj, (PyObject *)Py_TYPE(obj));
            if (res == NULL && suppress &&
                    PyErr_ExceptionMatches(PyExc_AttributeError)) {
                PyErr_Clear();
            }
            goto done;
        }
    
        if (descr != NULL) {
            res = descr;
            descr = NULL;
            goto done;
        }
    
        if (!suppress) {
            PyErr_Format(PyExc_AttributeError,
                         "'%.50s' object has no attribute '%U'",
                         tp->tp_name, name);
        }
      done:
        Py_XDECREF(descr);
        Py_DECREF(name);
        return res;
    }

setattr
在这里插入图片描述

int
    _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
                                     PyObject *value, PyObject *dict)
    {
        PyTypeObject *tp = Py_TYPE(obj);
        PyObject *descr;
        descrsetfunc f;
        PyObject **dictptr;
        int res = -1;
    
        if (!PyUnicode_Check(name)){
            PyErr_Format(PyExc_TypeError,
                         "attribute name must be string, not '%.200s'",
                         name->ob_type->tp_name);
            return -1;
        }
    
        if (tp->tp_dict == NULL && PyType_Ready(tp) < 0)
            return -1;
    
        Py_INCREF(name);
    
        descr = _PyType_Lookup(tp, name);
    
        if (descr != NULL) {
            Py_INCREF(descr);
            f = descr->ob_type->tp_descr_set;
            if (f != NULL) {
                res = f(descr, obj, value);
                goto done;
            }
        }
    
        if (dict == NULL) {
            dictptr = _PyObject_GetDictPtr(obj);
            if (dictptr == NULL) {
                if (descr == NULL) {
                    PyErr_Format(PyExc_AttributeError,
                                 "'%.100s' object has no attribute '%U'",
                                 tp->tp_name, name);
                }
                else {
                    PyErr_Format(PyExc_AttributeError,
                                 "'%.50s' object attribute '%U' is read-only",
                                 tp->tp_name, name);
                }
                goto done;
            }
            res = _PyObjectDict_SetItem(tp, dictptr, name, value);
        }
        else {
            Py_INCREF(dict);
            if (value == NULL)
                res = PyDict_DelItem(dict, name);
            else
                res = PyDict_SetItem(dict, name, value);
            Py_DECREF(dict);
        }
        if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
            PyErr_SetObject(PyExc_AttributeError, name);
    
      done:
        Py_XDECREF(descr);
        Py_DECREF(name);
        return res;
    }

hasattr
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
分配空间:分配记录slots内容指针的大小即可在这里插入图片描述在这里插入图片描述
看对象是否存在descr,若是(查找slots的属性正是如此),调用descr身上的tp_descr_get方法,并将方法的返回值作为这次属性查找的结果返回。
在这里插入图片描述
看一下tp_descr_get是什么样子
在这里插入图片描述在这里插入图片描述
slots对应的member->type是T_OBJECT_EX,根据member所记录的偏移值和类型,访问属性内存的代码了
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值