Python装饰器重载内置的使用

 更新时间:2024年01月16日 09:46:14   作者:梯阅线条  
本文主要介绍了Python装饰器重载内置的使用,详细介绍如何创建装饰器,如何使用装饰器来重载内置函数,具有一定的参考价值,感兴趣的可以了解一下

python2.x的新式类和python3.x的全部类,内置操作表达式调用,不会触发__getattr__()和__getattribute__()。参考《python的getattr和getattribute拦截内置操作》。

NO内置操作表达式(隐式调用)对应方法(显式调用)
1索引操作[i]__getitem__
2加法(连接)操作+__coerce__ __add__
3括号调用()__call__
4打印print()__str__

__coerce__:表示强制类型转换,使用加法(或连接)操作+时,不同类型会触发类型转换或者报错。

内置操作调用方式:隐式调用,即调用表达式;显式调用,即调用方法名。

1.1 Py3内置操作表达式调用无法委托

描述

内置操作的表达式调用,无法在python3.0下委托,因为不会触发__getattr__()和__getattribute__()。

示例

>>> def traceCall(*args):#跟踪调用
    if trace:
        print('['+','.join(map(str,args))+']')

        
>>> def accessCtrl(forbid):
    def onDecorator(aCls):
        class onInstance:
            def __init__(self,*args,**kargs):
                self.__wrapped=aCls(*args,**kargs)
            def __getattr__(self,attr):
                traceCall('getattr',attr)
                if forbid(attr):
                    raise TypeError('禁止访问:'+attr)
                else:
                    return getattr(self.__wrapped,attr)
            def __setattr__(self,attr,value):
                traceCall('setattr',attr,value)
                # 压缩后的变量名为 _onInstance__wrapped
                if attr=='_onInstance__wrapped':
                    self.__dict__[attr]=value
                elif forbid(attr):
                    raise TypeError('禁止设置:'+attr)
                else:
                    setattr(self.__wrapped,attr,value)
        return onInstance
    return onDecorator

>>> def privateAttr(*privates):
    return accessCtrl(forbid=(lambda attr:attr in privates))

>>> @privateAttr('phone')
class Staff_Private:
    def __init__(self,name,phone):
        self.name=name
        self.phone=phone
    def __str__(self):
        return 'Staff_Private->手机号:'+str(self.phone)
    def __add__(self,num):
        self.phone+=num

Python2.x执行

Py2的__getattr__()拦截print()和+等内置操作的表达式调用,正确的委托给装饰对象。

#python2.x执行
>>> trace=True
>>> sp1=Staff_Private('梯阅线条',110)
[setattr,_onInstance__wrapped,Staff_Private->手机号:110]
#py2传统类 拦截内置操作表达式调用-隐式调用,print()
>>> print(sp1)
[getattr,__str__]
Staff_Private->手机号:110
#py2传统类 拦截内置操作表达式调用-隐式调用,+
>>> sp1+1
[getattr,__coerce__]
[getattr,__add__]
>>> print(sp1)
[getattr,__str__]
Staff_Private->手机号:111

Python3.x执行

Py3的__getattr__()不拦截print()和+等内置操作的表达式调用,无法委托给装饰对象。

#python3.x执行
>>> trace=True
>>> sp1=Staff_Private('梯阅线条',110)
[setattr,_onInstance__wrapped,Staff_Private->手机号:110]
#py3没有拦截内置操作 print
>>> print(sp1)
<__main__.accessCtrl.<locals>.onDecorator.<locals>.onInstance object at 0x0000019736C2F4F0>
#py3没有拦截内置操作 + 
>>> sp1+1
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    sp1+1
TypeError: unsupported operand type(s) for +: 'onInstance' and 'int'

1.2 装饰器重载内置操作

描述

Python3.x的装饰器重载内置操作运算符方法,来拦截装饰类对应的内置表达式调用。

比如,重载__str__()拦截print(),__add__()拦截+。

示例

>>> def traceCall(*args):#跟踪调用
    if trace:
        print('['+','.join(map(str,args))+']')
>>> def accessCtrl(forbid):
    def onDecorator(aCls):
        class onInstance:
            def __init__(self,*args,**kargs):
                self.__wrapped=aCls(*args,**kargs)
            def __getattr__(self,attr):
                traceCall('getattr',attr)
                if forbid(attr):
                    raise TypeError('禁止访问:'+attr)
                else:
                    return getattr(self.__wrapped,attr)
            def __setattr__(self,attr,value):
                traceCall('setattr',attr,value)
                # 压缩后的变量名为 _onInstance__wrapped
                if attr=='_onInstance__wrapped':
                    self.__dict__[attr]=value
                elif forbid(attr):
                    raise TypeError('禁止设置:'+attr)
                else:
                    setattr(self.__wrapped,attr,value)
            # print()触发__str__()
            def __str__(self):
                traceCall('onInstance,__str__')
                # str()触发__str__()
                return str(self.__wrapped)
            # + 触发 __add__()    
            def __add__(self,other):
                traceCall('onInstance,__add__',other)
                return self.__wrapped+other
        return onInstance
    return onDecorator

>>> def privateAttr(*privates):
    return accessCtrl(forbid=(lambda attr:attr in privates))

>>> @privateAttr('phone')
class Staff_Private:
    def __init__(self,name,phone):
        self.name=name
        self.phone=phone
    def __str__(self):
        traceCall('Staff_Private,__str__')
        return 'Staff_Private->手机号:'+str(self.phone)
    def __add__(self,num):
        traceCall('Staff_Private,__add__',num)
        self.phone+=num

        
>>> trace=True
>>> sp1=Staff_Private('梯阅线条',110)
[Staff_Private,__str__]#traceCall调用print()触发__str__()
[setattr,_onInstance__wrapped,Staff_Private->手机号:110]
# print()触发__str__()
>>> print(sp1)
[onInstance,__str__]
[Staff_Private,__str__]
Staff_Private->手机号:110
# + 触发 __add__()
>>> sp1+1
[onInstance,__add__,1]
[Staff_Private,__add__,1]
>>> print(sp1)
[onInstance,__str__]
[Staff_Private,__str__]
Staff_Private->手机号:111

到此这篇关于Python装饰器重载内置的使用的文章就介绍到这了,更多相关Python装饰器重载内置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • pyqt6实现关闭窗口前弹出确认框的示例代码

    pyqt6实现关闭窗口前弹出确认框的示例代码

    本文主要介绍了pyqt6实现关闭窗口前弹出确认框的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • python中leastsq函数的使用方法

    python中leastsq函数的使用方法

    这篇文章主要介绍了python中leastsq函数的使用方法,leastsq作用是最小化一组方程的平方和,下面文章举例说明详细内容,具有一的参考价值,需要的小伙伴可以参考一下
    2022-03-03
  • python代码制作configure文件示例

    python代码制作configure文件示例

    这篇文章主要介绍了python代码如何制作configure文件,需要的朋友可以参考下
    2014-07-07
  • python中的路径拼接问题

    python中的路径拼接问题

    这篇文章主要介绍了python中的路径拼接问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Python文件操作模拟用户登陆代码实例

    Python文件操作模拟用户登陆代码实例

    这篇文章主要介绍了Python文件操作模拟用户登陆代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • python判断是空的实例分享

    python判断是空的实例分享

    在本篇内容里小编给大家整理的是关于python怎么判断是空的相关知识点内容,需要的朋友们学习下。
    2020-07-07
  • Python中利用all()来优化减少判断的实例分析

    Python中利用all()来优化减少判断的实例分析

    在本篇文章里小编给大家整理的是一篇关于Python中利用all()来优化减少判断的实例分析内容,有需要的朋友们可以学习下。
    2021-06-06
  • windows环境中利用celery实现简单任务队列过程解析

    windows环境中利用celery实现简单任务队列过程解析

    这篇文章主要介绍了windows环境中利用celery实现简单任务队列过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Python 字符串使用多个分隔符分割成列表的2种方法

    Python 字符串使用多个分隔符分割成列表的2种方法

    本文主要介绍了Python 字符串使用多个分隔符分割成列表,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 对python中类的继承与方法重写介绍

    对python中类的继承与方法重写介绍

    今天小编就为大家分享一篇对python中类的继承与方法重写介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01

最新评论