第六种方式,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 ...
随机推荐
- Java编程的逻辑 (66) - 理解synchronized
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 如何防止Arp攻击
首先需要查找网关的IP和MAC地址. 查看的方法很多,最直接的在cmd里面执行arp -a.但这是被arp攻击之前,被攻击成功后,192.168.0.1对应的mac地址会变成攻击电脑的Mac地址. 还 ...
- SQLSERVER SQL备份还原代码C#
public class BakDBHelper { /// <summary> /// 创建数据库备份 /// </summary> public string Create ...
- Python - 连接msql数据库
可能出现的异常:python中出现SyntaxError: Non-UTF-8 code 解决方法 刚开始一直有用idle写代码,今天用了一下PyDev结果发现中文不支持,在网上搜了一下,结果发现解决 ...
- Visual Studio 2013新建ASP.NET项目使用Empty模板,在页面中使用验证控件出错的解决方案
Visual Studio 2013新建ASP.NET项目使用Empty模板,在页面中使用验证控件,运行页面,会出现如下的错误: 错误原因 VisualStudio 2012(或2013) WebFo ...
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...
- Mac下安装Pyqt
1.安装sip brew install sip 2.安装pyqt brew install pyqt
- 关于”nodejs基于事件驱动”的思考
刚想通是怎么回事. 以页面上的js为例,你可以给多个标签注册事件回调,然而,无论给 多少个标签 注册 多少个事件回调,这些回调都只会等待自己命中注定的那个事件,在执行上都不会彼此影响!!! 再想一下w ...
- 第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页
第三百七十节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索结果分页 逻辑处理函数 计算搜索耗时 在开始搜索前:start_time ...
- SpringBoot系列四:SpringBoot开发(改变环境属性、读取资源文件、Bean 配置、模版渲染、profile 配置)
声明:本文来源于MLDN培训视频的课堂笔记,写在这里只是为了方便查阅. 1.概念 SpringBoot 开发深入 2.具体内容 在之前已经基本上了解了整个 SpringBoot 运行机制,但是也需要清 ...