python装饰器2:类装饰器
本文是装饰器相关内容的第二篇,关于类装饰器。
"类装饰器"有两种解读方式:用来装饰类的装饰器;类作为装饰器装饰其它东西。你如何认为取决于你,两种说法都有出现在其它的文章中。我的文章中是将"类装饰器"解读为第一种方式,即装饰类的东西。而“类作为装饰器装饰其它东西”,我都会为其标注"类作为装饰器"或"作为装饰器的类"以避免歧义。
类装饰器的形式
函数装饰器是装饰函数(方法)的,类装饰器是装饰类的,它们的表现形式是一样的。
@decorator
class cls:
...
c = cls()
等价于:
class cls:
...
cls = decorator(cls)
c = cls()
它的效果是创建实例对象的时候,会触发装饰器中的代码逻辑。
再细细一想,发现decorator(cls)
要返回的是一个类,所以decorator中的结构大概是这样的:
def decorator(cls):
class wrapper:
...
return wrapper
这样就会让被包装的类cls实际变成wrapper类,并且以后调用cls构造对象的时候,实际上是调用wrapper类来构造对象。换句话说,wrapper已经拦截了对所有的cls操作。
但并非一定如此,比如直接返回原始的cls:
def decorator(cls):
...do something about cls...
return cls
这种方式比较简单,本文主要对前一种方式进行详细解释。
由于返回的是class wrapper
,那么它装饰类的时候,假设所装饰的类有构造方法__init__
,构造方法中有属性,这个类中还有方法。如下:
@decorator
class cls(): # 等价于cls = decorator(cls)
def __init__(self, x, y):
self.attrx = x
self.attry = y
def method(self):
return self.x, self.y
那么在包装器wrapper中,需要能够构造出这个对象,并且能够取得被包装类的对象属性、类属性。如下:
def decorator(cls):
class wrapper():
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
return getattr(self.wrapped, name)
return wrapper
因为操作cls类的时候,实际上是在操作wrapper类。所以构造cls对象的时候:
c = cls(3, 4)
实际上是在调用wrapper(3, 4)
来构造对象,所以会执行wrapper里的__init__
。但类装饰器最终的目标是为了扩展类cls,所以在wrapper里必须得构造出cls的对象。上面采取的方式是通过cls()来构造cls对象,并放在wrapper对象的一个属性wrapped中。
因为cls已经被金蚕脱壳成了wrapper,所以要获取到cls的属性必须在wrapper中重写属性获取的方式。
下面是一个示例:
def decorator(cls):
class wrapper():
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
return getattr(self.wrapped, name)
return wrapper
@decorator
class cls():
def __init__(self, x, y):
self.attrx = x
self.attry = y
def method(self):
return self.attrx, self.attry
c = cls(3, 4)
print(c.attrx)
print(c.attry)
print(c.method())
输出结果:
3
4
(3, 4)
python装饰器2:类装饰器的更多相关文章
- python 进阶篇 函数装饰器和类装饰器
函数装饰器 简单装饰器 def my_decorator(func): def wrapper(): print('wrapper of decorator') func() return wrapp ...
- typescript装饰器定义 类装饰器 属性装饰器 装饰器工厂
/* 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为. 通俗的讲装饰器就是一个方法,可以注入到类.方法.属性参数上来扩展类.属性.方法.参数的功能. 常 ...
- Java类载入器(一)——类载入器层次与模型
类载入器 虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...
- 详解Python闭包,装饰器及类装饰器
在项目开发中,总会遇到在原代码的基础上添加额外的功能模块,原有的代码也许是很久以前所写,为了添加新功能的代码块,您一般还得重新熟悉源代码,稍微搞清楚一点它的逻辑,这无疑是一件特别头疼的事情.今天我们介 ...
- python高级 之(二) --- 类装饰器
装饰器-初级 在不改变原有函数逻辑功能的基础上,为函数添加新的逻辑功能.使代码可读性更高.结构更加清晰.冗余度更低 简介 """ 闭包: 函数嵌套的格式就是闭包.写装饰器 ...
- [b0019] python 归纳 (五)_类装饰器
总结: 类装饰器, 本质是一个函数,输入一个类,返回一个类 Case 1 啥都没做 def deco(in_class): return in_class @deco class Cat: def _ ...
- python带参数的类装饰器
# -*- coding: utf-8 -*- # author:baoshan # 带参数的类装饰器(和不带参数的类装饰器有很大的不同) # 类装饰器的实现,必须实现__call__和__init_ ...
- python 装饰器(五):装饰器实例(二)类装饰器(类装饰器装饰函数)
回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文). 那么用类来实现也是也可以的.我们可以让类的构造函数__init__()接受一个函 ...
- python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类
一:函数装饰函数 def wrapFun(func): def inner(a, b): print('function name:', func.__name__) r = func(a, b) r ...
- Python入门之python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类
一:函数装饰函数 def wrapFun(func): def inner(a, b): print('function name:', func.__name__) r = func(a, b) r ...
随机推荐
- java 调用 api接口
/* * Copyright 2018 textile.com All right reserved. This software is the * confidential and propriet ...
- Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并(转)
Git Gui for Windows的建库.克隆(clone).上传(push).下载(pull).合并(转) from:http://hi.baidu.com/mvp_xuan/blog/item ...
- Minimum setup for Apache+AD SSO
参照: http://www.grolmsnet.de/kerbtut/ https://docs.typo3.org/typo3cms/extensions/ig_ldap_sso_auth/2.1 ...
- Exp2 后门原理与实践-------20164325王晓蕊
Exp2 后门原理与实践 任务一:使用netcat获取主机操作Shell,cron启动 1.windows获取linux shell 1.1 ipconfig 查看本机查看以太网适配器(8)的ipv ...
- 插入排序之Java实现
插入排序类似于大多数人安排扑克牌的方式. 1.从你手中的一张牌开始, 2.选择下一张卡并将其插入到正确的排序顺序中, 3.对所有的卡重复上一步. /** * * 代码理解:只需要记住两点: * 1.当 ...
- Python之旅Day15 Bootstrap与Django初识
Bootstrap初识 Bootstrap简介 Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目.(官网http://www.boo ...
- [转]CSS clear both清除浮动
DIV+CSS clear both清除产生浮动 我们知道有时使用了css float浮动会产生css浮动,这个时候就需要清理清除浮动,我们就用clear样式属性即可实现. 接下来我们来认识与学习cs ...
- spark-submit(spark版本2.4.2)
spark-submit官方文档 :http://spark.apache.org/docs/latest/submitting-applications.html Launching Applica ...
- Android之.9图的知识
Android之.9图的知识 .9图的介绍 .9图也称为pPatch图,它是android app开发里一种特殊的图片形式,文件的扩展名为:.9.png. 9patch图片的作用就是在图片拉伸的时候保 ...
- HDFS第一次课堂测试
起初在linux上想使用Map/Reduce来完成操作,发现需要导入的jar包过多,大概在6点左右写完程序却跑不起来,一直在找jar包,直接被卡死在这里. 从教室回来之后,发现好多人都是在window ...