第五种方式,python使用组合来添加类方法和属性(二),以selenium的webdriver为例

组合优点多,但经常比继承需要额外的代码。

 上一篇是 介绍装饰器、继承、元类、mixin,四种給类动态添加类属性和方法的四种方式。

此篇介绍直接把被组合的类的属性直接加入到类里面,前面的四个例子很简单,这次来个实际例子的举例。

# coding:utf-8

import logging
import unittest
from selenium import webdriver


class DriverWrapper():
    def __init__(self):
        self.driver = webdriver.Chrome()
        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)

    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()

1、这样就是组合来动态添加方法和属性了,DriverWrapper类的实例可以直接使用一切Chrome类的实例的方法和属性。

2、如果不重写__getattr__方法,那么driver_wrapper.find_element_by_id('kw')  这么做就会报错,因为DriverWrapper类没有定义过这个方法。

一共五种方法动态扩展。

但元类 装饰器 和此篇的组合然后重写__getattr__来添加方法和属性,有个重大弊端是,因为太动态了,pycharm写代码时候,不能自动补全这些被扩展添加的方法和属性,这个是硬伤,因为pycahrm只能普通的代码理解,但整段的代码运行结果他理解不了。然后看代码时候苦难一点。

 

原文地址:https://www.cnblogs.com/ydf0509/p/9213793.html