使用 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类无限实例化控制成单浏览器。的更多相关文章

  1. python类属性和类方法(类的结构、实例属性、静态方法)

    类属性和类方法 目标 类的结构 类属性和实例属性 类方法和静态方法 01. 类的结构 1.1 术语 —— 实例 使用面相对象开发,第 1 步 是设计 类 使用 类名() 创建对象,创建对象 的动作有两 ...

  2. python 四种方法修改类变量,实例对象调用类方法改变类属性的值,类对象调用类方法改变类属性的值,调用实例方法改变类属性的值,直接修改类属性的值

    三种方法修改类变量,实例对象调用类方法改变类属性的值,类对象调用类方法改变类属性的值,调用实例方法改变类属性的值,类名就是类对象,city就是类变量, #coding=utf-8 class empl ...

  3. python干货-类属性和方法,类的方法重写

    类属性与方法 类的私有属性 __private_attrs: 两个下划线开头,表明为私有,外部不可用,内部使用时self.__private_attrs. 类的方法 在类的内部,使用 def 关键字来 ...

  4. python小知识-属性查询优先级(如果有同名类属性、数据描述符、实例属性存在的话,实例>类>数据描述符)

    https://www.cnblogs.com/Jimmy1988/p/6808237.html https://segmentfault.com/a/1190000006660339 https:/ ...

  5. python类属性用法总结

    属性的定义:python中的属性其实是普通方法的衍生. 操作类属性有三种方法: 1.使用@property装饰器操作类属性. 2.使用类或实例直接操作类属性(例如:obj.name,obj.age=1 ...

  6. python3 速查参考- python基础 8 -> 面向对象基础:类的创建与基础使用,类属性,property、类方法、静态方法、常用知识点概念(封装、继承等等见下一章)

    基础概念 1.速查笔记: #-- 最普通的类 class C1(C2, C3): spam = 42 # 数据属性 def __init__(self, name): # 函数属性:构造函数 self ...

  7. Python之路-面向对象&继承和多态&类属性和实例属性&类方法和静态方法

    一.面向对象 编程方式 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强…” 什么是面 ...

  8. 我的Python学习笔记(四):动态添加属性和方法

    一.动态语言与静态语言 1.1 动态语言 在运行时代码可以根据某些条件改变自身结构 可以在运行时引进新的函数.对象.甚至代码,可以删除已有的函数等其他结构上的变化 常见的动态语言:Object-C.C ...

  9. 【17】有关python面向对象编程的提高【多继承、多态、类属性、动态添加与限制添加属性与方法、@property】

    一.多继承 案例1:小孩继承自爸爸,妈妈.在程序入口模块再创建实例调用执行 #father模块 class Father(object): def __init__(self,money): self ...

随机推荐

  1. update更新另一个字段

    1. 写法轻松,更新效率高:update table1 set field1=table2.field1,field2=table2.field2from table2where table1.id= ...

  2. Linux(CentOS)日常操作命令

    用硬件检测程序kuduz探测新硬件:service kudzu start (or restart)查看CPU信息:cat /proc/cpuinfo查看板卡信息:cat /proc/pci查看PCI ...

  3. 获取最后插入的id另外方法

    在此记录备忘. CREATE TABLE tb_test(custid INT IDENTITY(1,1) NOT NULL , name nvarchar(200) NOT NULL) DECLAR ...

  4. android studio 解析Excel数据格式导入poi-3.17.jar时的一系列报错及处理Failed resolution of: Ljavax/xml/stream/XMLEventFactory,duplicate entry: org/apache/xmlbeans/xml/stream/Location.class,GC overhead limit exceeded

    在org官网下载的poi jar包,导入到studio compile files('libs/poi-3.17.jar') compile files('libs/poi-ooxml-3.17.ja ...

  5. r语言 列出所有变量

    你希望知道目前工作空间中存在哪些已定义的变量和函数. 解决方案 使用ls函数,或者使用ls.str函数了解每个变量更详细的信息. 讨论 ls函数可以显示当前工作空间中所有对象的名称:> x &l ...

  6. 自然语言交流系统 phxnet团队 创新实训 项目博客 (五)

    3DMax方面所涉及的专业知识:                       (1)一下的关于3DMax中对于人物的设计和操作均需要在对3DMax基础知识熟练掌握的情况下进行的. (2)骨骼架设:首先 ...

  7. 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从

    明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的 ...

  8. 【Vue】VS Code+Vue入门 Helloworld

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. e825. 当JSplitPane改变大小时分配空间

    The weight of a split pane controls the behavior of the divider when the split pane is resized. If t ...

  10. unity---gameScreen 的Stats参数

    Unity Stats 面板介绍 原创 2016年06月12日 10:06:12 1544 0 3 Time per frame and FPS (每帧的时间和FPS):处理和渲染一个游戏框架(以及由 ...