第六种方式,python使用cached_property缓存装饰器和自定义cached_class_property装饰器,动态添加类属性(三),selnium webdriver类无限实例化控制成单浏览器。
使用 from lazy_object_proxy.utils import cached_property,使用这个装饰器。
由于官方的行数比较少,所以可以直接复制出来用自己的。
class cached_property(object): # 这是官方的
def __init__(self, func):
self.func = func def __get__(self, obj, cls):
print (obj,cls)
if obj is None: return self
value = obj.__dict__[self.func.__name__] = self.func(obj)
return value class cached_class_property(object): # 这是修改的
def __init__(self, func):
self.func = func def __get__(self, obj, cls):
print (obj,cls)
if obj is None: return self
value = cls.__dict__[self.func.__name__] = self.func(obj)
return value class A():
@cached_property # 使用这个实例属性的缓存装饰器,然后替换为property装饰器和自定义的cached_class_property测试
def result(self):
print ('compute result')
return 1+2 a1 = A()
a1.result # 第一次
a1.result # 第二次
a2 = A()
a2.result # 第三次
1、如果使用cached_property这个装饰器,是把result方法的结果绑定到实例的字典中,所以一共打印了两次 'compute result' ,分别是第一次 第三次打印的,第二次因为a1这个实例的字典中有result这个属性了,所以不执行这个方法了。
2、 如果使用property装饰器,毫无疑问就是会打印三次 'compute result'
3、下面来个更激进一点的装饰器,cached_property这个实例属性装饰器虽然能缓存结果,但是新的实例还是会调用这个方法进行1+2计算。做一点小改变,把obj.__dict__换成cls.__dict__,也就是改成cached_class_property,这样就是类属性缓存器,这样就只会打印一次'compute result'了,perfect了,利用这个对基类添加动态属性太好了,好处包括:
1)不像之前的元类和那种装饰器写法,动态添加进来的属性和方法,使用时候不能在pycharm自动补全提示,说的补全指的是打 self.r 就会补全出self.result,打self.result.就会补全出一个整形int类的所有方法了,因为1+2等于3,3是整形。
2、相比于基类在__init__或者new中添加方法,如果动态添加属性的类作为基类被继承,当子类也写了init方法时候,必须显式手动去调用父类的init方法。
4、这只是举个例子,1 + 2这么简单的东西不需要使用缓存的,如果调用result属性不频繁是没必要使用这个装饰器的,但有的对象创建是经过了很久的运行步骤的,当频繁使用这个属性,造成很多没必要的计算,或者有的结果是一个io过程得到的,更要使用这样装饰器了。用这个作为selenium的webdriver包装类的driver属性也很不错,加上他,就可以十分任性的随意实例化你写的webdriver类了,不会每实例化一次都新弹出一次浏览器。 从包的名字就可以看出缓存器也叫延迟加载,如果直接写成类属性那么还没开始使用这个属性就已经执行运算了,比如直接写成类下面作为类属性,还没准备需要使用浏览器,就早早的弹出个浏览器出来,没什么必要。
5、把上一篇的webdriver改一下,控制为单浏览器就是这样了。
# coding:utf-8 import logging
import unittest
from selenium import webdriver class DriverWrapper():
def __init__(self): self.logger = logging.getLogger(self.__class__.__name__)
self.logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S"))
self.logger.addHandler(stream_handler)
@cached_class_property ## 添加一个类属性缓存装饰器
def driver(self):
self.driver = webdriver.Chrome() def open(self, url):
self.driver.get(url) def find_element_by_css_selector(self, css_str): # 使用自定义的方法覆盖了原方法,比如先打印出一段话
self.logger.debug('要查找的元素的css选择器是 --> ' + css_str)
self.driver.find_element_by_css_selector(css_str) def __getattr__(self, item): #想把其他的webdriver的操作方法直接添加进来,不一个一个的再写一个方法然后调用driver属性的方法,不想一直搞冗余的代码,可以这么做。python先使用__getattribute__,查不到才会调用__getsttr__方法,利用这个特性,来实现这个添加driver的属性到自己类里面
return getattr(self.driver, item) class _Test(unittest.TestCase):
def test(self):
driver_wrapper = DriverWrapper()
driver_wrapper.open('https://www.baidu.com') # 有人不喜欢用get,可以叫open什么的
driver_wrapper.find_element_by_css_selector('#kw') # 当类中存在方法,使用了自己类里面的方法,所以每次使用css选择器查找元素时候会打印一个日志
driver_wrapper.find_element_by_id('kw') # 当类中不存在此方法,使用Chrome类的方法 driver_warpper.driver.close() # 这样做也可以,但不算是动态添加属性了,这是直接使用的该实例的driver属性的方法,driver属性是Chrome的一个实例。 if __name__ == '__main__':
unittest.main()
6、此时就可以非常任性的在任何测试用例中任何函数中去实例化DriverWrapper类了,而不用依赖有webdriver实例化的测试用例方法必须先运行
7、无限实例化DriverWrapper类还想弄成单浏览器也可以借鉴享元模式或者单例模式。但抽成装饰器后,使用到其他的类中也是通用的,节约代码。不然很多代码中出现同一段相似的判断,看着稍微low点。
第六种方式,python使用cached_property缓存装饰器和自定义cached_class_property装饰器,动态添加类属性(三),selnium webdriver类无限实例化控制成单浏览器。的更多相关文章
- python类属性和类方法(类的结构、实例属性、静态方法)
类属性和类方法 目标 类的结构 类属性和实例属性 类方法和静态方法 01. 类的结构 1.1 术语 —— 实例 使用面相对象开发,第 1 步 是设计 类 使用 类名() 创建对象,创建对象 的动作有两 ...
- python 四种方法修改类变量,实例对象调用类方法改变类属性的值,类对象调用类方法改变类属性的值,调用实例方法改变类属性的值,直接修改类属性的值
三种方法修改类变量,实例对象调用类方法改变类属性的值,类对象调用类方法改变类属性的值,调用实例方法改变类属性的值,类名就是类对象,city就是类变量, #coding=utf-8 class empl ...
- python干货-类属性和方法,类的方法重写
类属性与方法 类的私有属性 __private_attrs: 两个下划线开头,表明为私有,外部不可用,内部使用时self.__private_attrs. 类的方法 在类的内部,使用 def 关键字来 ...
- python小知识-属性查询优先级(如果有同名类属性、数据描述符、实例属性存在的话,实例>类>数据描述符)
https://www.cnblogs.com/Jimmy1988/p/6808237.html https://segmentfault.com/a/1190000006660339 https:/ ...
- python类属性用法总结
属性的定义:python中的属性其实是普通方法的衍生. 操作类属性有三种方法: 1.使用@property装饰器操作类属性. 2.使用类或实例直接操作类属性(例如:obj.name,obj.age=1 ...
- python3 速查参考- python基础 8 -> 面向对象基础:类的创建与基础使用,类属性,property、类方法、静态方法、常用知识点概念(封装、继承等等见下一章)
基础概念 1.速查笔记: #-- 最普通的类 class C1(C2, C3): spam = 42 # 数据属性 def __init__(self, name): # 函数属性:构造函数 self ...
- Python之路-面向对象&继承和多态&类属性和实例属性&类方法和静态方法
一.面向对象 编程方式 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强…” 什么是面 ...
- 我的Python学习笔记(四):动态添加属性和方法
一.动态语言与静态语言 1.1 动态语言 在运行时代码可以根据某些条件改变自身结构 可以在运行时引进新的函数.对象.甚至代码,可以删除已有的函数等其他结构上的变化 常见的动态语言:Object-C.C ...
- 【17】有关python面向对象编程的提高【多继承、多态、类属性、动态添加与限制添加属性与方法、@property】
一.多继承 案例1:小孩继承自爸爸,妈妈.在程序入口模块再创建实例调用执行 #father模块 class Father(object): def __init__(self,money): self ...
随机推荐
- PostgreSQL ALTER TABLE中改变数据类型时USING的用法<转>
在修改表字段类型的时候使用Using来进行显示的转换类型. 原文说明: SET DATA TYPE This form changes the type of a column of a table ...
- STM32f103的数电采集电路的双ADC的设计与使用
STM32F103C8T6拥有3个ADC,其独立使用已经在本文的3.1.3里面有详细的介绍,这里主要是介绍双ADC的同时使用,即STM32的同步规则模式使用.在此模式在规则通道组上执行时,外部触发来自 ...
- Android——Fragment实例精讲——底部导航栏+ViewPager滑动切换页面
说明: 实现效果: 1- 用ViewPager实现Fragmen之间的切换 2- 底部用RadioGroup实现,更方便的实现图片和字体颜色的改变,更方便的通过RadioButton的点击事件来控制页 ...
- Android——线程通讯类Handler(转)
原文地址:http://uule.iteye.com/blog/1705951 handler是线程通讯工具类.用于传递消息.它有两个队列:1.消息队列2.线程队列 消息队列使用sendMessage ...
- 你真的理解devDependencies和dependencies区别吗?
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/achenyuan/article/details/80899783 网上统一的观念是 devDep ...
- dd 命令 sd卡系统迁移
Linux系统如果想做备份还原,使用ghost的时候经常出现问题,后来发现可以直接使用dd命令完成硬盘的克隆和还原.当拷贝完硬盘后,就可以拿这个硬盘放到其它设备上跑了.也就是完成了“烧写”了. 实际操 ...
- 树莓派 NOOBS 安装系统
Raspberry Pi Foundation发布了一个名为“New Out of Box Software”(NOOBS)的工具,可以用来方便的安装系统,让我们尝试一下这个新的安装工具. 以我的树莓 ...
- 第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成
第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成 apps目录建立 我们创建一个apps目录,将所有的app放到apps目录里去,这样方便管理,也 ...
- e782. 排列JList中的项
By default, the items in a list are arranged vertically, in a single column, as in: item1 item2 ... ...
- interpro 数据库
interpro 通过整合多个蛋白相关的数据库,提供了一个方便的对蛋白序列进行功能注释的平台,功能注释的内容包括蛋白质家族预测,domain 和 结合位点预测 interoro 在整合多个数据库的同时 ...