电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Python如何將裝飾器定義為類

瀏覽:5日期:2022-07-15 18:32:49

問題

你想使用一個裝飾器去包裝函數,但是希望返回一個可調用的實例。 你需要讓你的裝飾器可以同時工作在類定義的內部和外部。

解決方案

為了將裝飾器定義成一個實例,你需要確保它實現了 __call__() 和 __get__() 方法。 例如,下面的代碼定義了一個類,它在其他函數上放置一個簡單的記錄層:

import typesfrom functools import wrapsclass 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)

你可以將它當做一個普通的裝飾器來使用,在類里面或外面都可以:

@Profileddef add(x, y): return x + yclass Spam: @Profiled def bar(self, x): print(self, x)

在交互環境中的使用示例:

>>> add(2, 3)5>>> add(4, 5)9>>> add.ncalls2>>> s = Spam()>>> s.bar(1)<__main__.Spam object at 0x10069e9d0> 1>>> s.bar(2)<__main__.Spam object at 0x10069e9d0> 2>>> s.bar(3)<__main__.Spam object at 0x10069e9d0> 3>>> Spam.bar.ncalls3

討論

將裝飾器定義成類通常是很簡單的。但是這里還是有一些細節需要解釋下,特別是當你想將它作用在實例方法上的時候。

首先,使用 functools.wraps() 函數的作用跟之前還是一樣,將被包裝函數的元信息復制到可調用實例中去。

其次,通常很容易會忽視上面的 __get__() 方法。如果你忽略它,保持其他代碼不變再次運行, 你會發現當你去調用被裝飾實例方法時出現很奇怪的問題。例如:

>>> s = Spam()>>> s.bar(3)Traceback (most recent call last):...TypeError: bar() missing 1 required positional argument: ’x’

出錯原因是當方法函數在一個類中被查找時,它們的 __get__() 方法依據描述器協議被調用, 在8.9小節已經講述過描述器協議了。在這里,__get__() 的目的是創建一個綁定方法對象 (最終會給這個方法傳遞self參數)。下面是一個例子來演示底層原理:

>>> s = Spam()>>> def grok(self, x):... pass...>>> grok.__get__(s, Spam)<bound method Spam.grok of <__main__.Spam object at 0x100671e90>>>>>

__get__() 方法是為了確保綁定方法對象能被正確的創建。 type.MethodType() 手動創建一個綁定方法來使用。只有當實例被使用的時候綁定方法才會被創建。 如果這個方法是在類上面來訪問, 那么 __get__() 中的instance參數會被設置成None并直接返回 Profiled 實例本身。 這樣的話我們就可以提取它的 ncalls 屬性了。

如果你想避免一些混亂,也可以考慮另外一個使用閉包和 nonlocal 變量實現的裝飾器,這個在9.5小節有講到。例如:

import typesfrom functools import wrapsdef profiled(func): ncalls = 0 @wraps(func) def wrapper(*args, **kwargs): nonlocal ncalls ncalls += 1 return func(*args, **kwargs) wrapper.ncalls = lambda: ncalls return wrapper# Example@profileddef add(x, y): return x + y

這個方式跟之前的效果幾乎一樣,除了對于 ncalls 的訪問現在是通過一個被綁定為屬性的函數來實現,例如:

>>> add(2, 3)5>>> add(4, 5)9>>> add.ncalls()2>>>

以上就是Python如何將裝飾器定義為類的詳細內容,更多關于Python將裝飾器定義為類的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 选矿设备,选矿生产线,选矿工艺,选矿技术-昆明昆重矿山机械 | 烟台条码打印机_烟台条码扫描器_烟台碳带_烟台数据采集终端_烟台斑马打印机-金鹏电子-金鹏电子 | 防爆大气采样器-防爆粉尘采样器-金属粉尘及其化合物采样器-首页|盐城银河科技有限公司 | X光检测仪_食品金属异物检测机_X射线检测设备_微现检测 | 工控机-图像采集卡-PoE网卡-人工智能-工业主板-深圳朗锐智科 | 贵阳用友软件,贵州财务软件,贵阳ERP软件_贵州优智信息技术有限公司 | STRO|DTRO-STRO反渗透膜(科普)_碟滤 | 智能汉显全自动量热仪_微机全自动胶质层指数测定仪-鹤壁市科达仪器仪表有限公司 | 西安标准厂房_陕西工业厂房_西咸新区独栋厂房_长信科技产业园官方网站 | 烟气换热器_GGH烟气换热器_空气预热器_高温气气换热器-青岛康景辉 | 电机修理_二手电机专家-河北豫通机电设备有限公司(原石家庄冀华高压电机维修中心) | 烘箱-工业烘箱-工业电炉-实验室干燥箱 - 苏州华洁烘箱制造有限公司 | 路斯特伺服驱动器维修,伦茨伺服驱动器维修|万骏自动化百科 | 无纺布包装机|径向缠绕包装机|缠绕膜打包机-上海晏陵智能设备有限公司 | 复盛空压机配件-空气压缩机-复盛空压机(华北)总代理 | 电伴热系统施工_仪表电伴热保温箱厂家_沃安电伴热管缆工业技术(济南)有限公司 | 螺旋丝杆升降机-SWL蜗轮-滚珠丝杆升降机厂家-山东明泰传动机械有限公司 | 一体化污水处理设备_生活污水处理设备_全自动加药装置厂家-明基环保 | 温湿度记录纸_圆盘_横河记录纸|霍尼韦尔记录仪-广州汤米斯机电设备有限公司 | 仿真植物|仿真树|仿真花|假树|植物墙 - 广州天昆仿真植物有限公司 | 阴离子聚丙烯酰胺价格_PAM_高分子聚丙烯酰胺厂家-河南泰航净水材料有限公司 | 水上浮桥-游艇码头-浮动码头-游船码头-码瑞纳游艇码头工程 | 盘扣式脚手架-附着式升降脚手架-移动脚手架,专ye承包服务商 - 苏州安踏脚手架工程有限公司 | 电动手术床,医用护理床,led手术无影灯-曲阜明辉医疗设备有限公司 | 智慧物联网行业一站式解决方案提供商-北京东成基业 | 并网柜,汇流箱,电控设备,中高低压开关柜,电气电力成套设备,PLC控制设备订制厂家,江苏昌伟业新能源科技有限公司 | TPE_TPE热塑性弹性体_TPE原料价格_TPE材料厂家-惠州市中塑王塑胶制品公司- 中塑王塑胶制品有限公司 | 信阳网站建设专家-信阳时代网联-【信阳网站建设百度推广优质服务提供商】信阳网站建设|信阳网络公司|信阳网络营销推广 | 河南砖机首页-全自动液压免烧砖机,小型砌块水泥砖机厂家[十年老厂] | 微型实验室真空泵-无油干式真空泵-微型涡旋耐腐蚀压缩机-思科涡旋科技(杭州)有限公司 | CCE素质教育博览会 | CCE素博会 | 教育展 | 美育展 | 科教展 | 素质教育展 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | PC阳光板-PC耐力板-阳光板雨棚-耐力板雨棚,厂家定制[优尼科板材] | 电磁铁_推拉电磁铁_机械手电磁吸盘电磁铁厂家-广州思德隆电子公司 | 上海噪音治理公司-专业隔音降噪公司-中广通环保 | 美国PARKER齿轮泵,美国PARKER柱塞泵,美国PARKER叶片泵,美国PARKER电磁阀,美国PARKER比例阀-上海维特锐实业发展有限公司二部 | 金现代信息产业股份有限公司--数字化解决方案供应商 | 隔离变压器-伺服变压器--输入输出电抗器-深圳市德而沃电气有限公司 | 精密模具加工制造 - 富东懿| 南京PVC快速门厂家南京快速卷帘门_南京pvc快速门_世界500强企业国内供应商_南京美高门业 | 医用酒精_84消毒液_碘伏消毒液等医用消毒液-漓峰消毒官网 |