python系列整理---面向对象

一.基本概念  

  1. 类是抽象的,具有相同属性和方法(行为)的集合
  2. 对象是具体的,具有某些属性和方法(行为)的
  3. 创建的对象的过程,叫实例化
  4. 属性与方法
    1) 实例属性:self动态方式调用、赋值,及self.leg='new leg'仅限于当前对象
    2) 实例方法:   同上
    3) 静态属性:   以self动态方式调用、赋值时,仅限于当前对象;直接对静态属性Animal.leg='leg'调用时,贯穿所有对象
    4) 静态方法:   同上
    5) 类属性
    6) 类方法

二.继承   

  1.继承了父类的基本属性和方法
  2.可以继续实现自己的属性和方法
  3.方法重写:同名函数重写,用另一种实现方案实现父类的方法

class SetOperation:

    all_dict = {}

    def __init__(self, s1, s2):
        self.s1 = s1
        self.s2 = s2
        self._dict = {}
        self.set()
        # __var private 私有变量, 仅当前类内部使用, 外部不可直接访问,子类也不能继承
        # __method__ protect 魔法方法, 它只允许在该类的内部中使用, 意味着这个方法子类不能被重写 (继承)
        ## _var, __var__ 变量的访问权限没有限制
        ## _method, protect私有方法, 仅当前类内部使用

        self._instance = '_aaa'
        self.__instance = '__aaa'
        self.__instance__ = '__aaa__'
        self.s3 = None
        self.s4 = None

    def set(self):
        # 字典计数
        for i in self.s1:
            self._dict[i] = self._dict.get(i, 0) + 1
        for j in self.s2:
            self._dict[j] = self._dict.get(j, 0) + 1

    def set3(cls, s1, s2):
        cls.s1 = s1
        cls.s2 = s2

    @staticmethod
    def set2(s1, s2):
        # 字典计数
        for i in s1:
            SetOperation.all_dict[i] = SetOperation.all_dict.get(i, 0) + 1
        for j in s2:
            SetOperation.all_dict[j] = SetOperation.all_dict.get(j, 0) + 1

    def get(self):
        intersect, union, s12, s21 = set(), set(), set(), set()
        # 字典分类
        for k, v in self._dict.items():
            union.add(k)
            if v > 1:
                intersect.add(k)
            else:
                if k in self.s:
                    s12.add(k)
                else:
                    s21.add(k)
        return [intersect, union, s12, s21]

    def intersect(self):
        print('self._dict')
        intersect = set()
        for k, v in self._dict.items():
            if v > 1:
                intersect.add(k)
        return intersect

    def union(self):
        # return set(self._dict.keys())
        union = set()
        for k, v in self._dict.items():
            union.add(k)
        return union

    def set_b(self):
        self._instance = '_bbb'
        self.__instance = '__bbb'
        self.__instance__ = '__bbb___'
        print(f'{self.__class__.__name__}\t_instance\t{self._instance}')
        print(f'{self.__class__.__name__}\t__instance\t{self.__instance}')
        print(f'{self.__class__.__name__}\t__instance__\t{self.__instance__}')

    def get_b(self):
        print(f'{self.__class__.__name__}\t_instance\t{self._instance}')
        print(f'{self.__class__.__name__}\t__instance\t{self.__instance}')
        print(f'{self.__class__.__name__}\t__instance__\t{self.__instance__}')

    def _set_b(self):
        self.s4 = 'ttttt'

    def __set_b__(self):
        self.s3 = 'sssss'

    def __setitem__(self, key, value):
        """
        属性变量赋值时会调用__setitem__,
        区别在于如果将对象当作字典操作,设置键值对时会触发该方法,
        同样在__setitem__(self, key, value)方法内对属性进行赋值时,
        也不能使用self.name = value,而应该使用self.__dict__['name'] = value.
        """
        print(f'__setitem__: {key}--->{value}')
        self.__dict__[key] = value

    def __getitem__(self, item):
        return self.__dict__.get(item)

    def __setattr__(self, key, value):
        """
        属性变量赋值时会调用__setattr__,
        应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value
        """
        print(f'__setattr__: {key}--->{value}')
        self.__dict__[key] = value

    def __getattr__(self, item):
        return self.__dict__.get(item)

# 4个方法
class SetOperation2(SetOperation):
    """
    继承了父类的基本属性和方法
    可以继续实现自己的属性和方法
    方法重写:同名函数重写,用另一种实现方案实现父类的方法
    """

    def __init__(self, s1, s2):
        SetOperation.__init__(self, s1, s2)
        self.child = {}
        print('self.__instance:', self.__instance)
        self._instance = '_child'
        self.__instance = '__child'
        self.__instance__ = '__child__'

        # super().__init__(s1, s2)
        # self.s1 = s1
        # self.s2 = s2

    def intersect(self):
        print('self.s1 | self.s2')
        return self.s1 | self.s2

    def union(self):
        return self.s1 & self.s2

    def s12(self):
        return self.s1 - self.s2

    def s21(self):
        return self.s2 - self.s1

    def __set_b__(self):
        self.s3 = '33333'

三.设计模式

  1. 装饰器

# coding=utf-8
import time
from functools import wraps
import traceback


def stat_time(func):
    """统计函数或方法运行的时间"""
    @wraps(func)
    def opt(*arg, **kwargs):
        start_time = time.time()
        func(*arg, **kwargs)
        end_time = time.time()
        cha_time = end_time - start_time
        print(f'{func.__name__} method spend time {round(cha_time, 3)}')
    return opt


def retry(max_times=3):
    def retry_func(func):
        @wraps(func)
        def wrapper(*arg, **kwargs):
            res = None
            for i in range(max_times):
                try:
                    res = func(*arg, **kwargs)
                    break
                except:
                    print(traceback.print_exc())
            return res
        return wrapper
    return retry_func


if __name__ == '__main__':

    @retry(3)
    def abc():
        return 3 / 0

    abc()

  2. 单实例

# coding=utf-8
from functools import wraps


class Singleton:

    instance_pool = {}
    instance_pool_list = []


class SingletonType(type):
    """
    最优先使用的方式, 此种方法定义的单实例可以被继承
    1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
    2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法
    """
    def __call__(cls, *args, **kwargs):
        cls_key = (cls.__name__, args, tuple(kwargs.items()))
        cls_instance = Singleton.instance_pool.get(cls_key, None)
        if not cls_instance:
            cls_instance = super(SingletonType, cls).__call__(*args, **kwargs)
            Singleton.instance_pool[cls_key] = cls_instance
        return cls_instance


class SingletonListType(type):
    """
    和SingletonType一样, 此种方法定义的单实例的类【可以被继承】
    1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
    2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法
    """
    def __call__(cls, *args, **kwargs):
        for _cls_name, _args, _kwargs, _instance in Singleton.instance_pool_list:
            if (_cls_name, _args, _kwargs) == (cls.__name__, args, kwargs):
                return _instance
        else:
            _instance = super(SingletonListType, cls).__call__(*args, **kwargs)
            Singleton.instance_pool_list.append((cls.__name__, args, kwargs, _instance))
            return _instance


class SingletonDecClass:
    """
    使用装饰器方法,但此种方法定义的单实例的类【不可以被继承】
    1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)
    2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法
    """
    def __init__(self, cls):
        self.cls = cls

    def __call__(self, *args, **kwargs):
        for _cls_name, _args, _kwargs, _instance in Singleton.instance_pool_list:
            if (_cls_name, _args, _kwargs) == (self.cls.__name__, args, kwargs):
                return _instance
        else:
            _instance = self.cls(*args, **kwargs)
            Singleton.instance_pool_list.append((self.cls.__name__, args, kwargs, _instance))
            return _instance


class SingletonDecMethod(object):
    """
    使用装饰器方法,但此种方法定义的单实例的类【不可以被继承】
    """

    @staticmethod
    def singleton(cls):
        # 定义一个私有方法,wraps作用不知道的自己查,不感兴趣的也不用知道
        @wraps(cls)
        def __wrapper(*args, **kwargs):
            cls_key = (cls.__name__, args, kwargs)
            cls_instance = Singleton.instance_pool.get(cls_key)
            if not cls_instance:
                cls_instance = cls(*args, **kwargs)
                cls._instance_pool[cls_key] = cls_instance
            return cls_instance
        return __wrapper


class SingletonExample(object):
    """
    使用 __new__ 定义单实例
    正常定义类的模式, 需要重写 __new__方法
    """
    _instance = None

    def __init__(self, *args, **kwargs):
        pass

    def function(self, *args, **kwargs):
        pass

    def __new__(cls, *args, **kwargs):
        if not SingletonExample._instance:
            SingletonExample._instance = object.__new__(cls, *args, **kwargs)
        return SingletonExample._instance

  3. 工厂模式

           组成:

    1. 工厂基类,用来复制-扩展规模,提供一个抽象化的接口来创建一个特定类型的对象 
    2. 工厂函数类,通过继承工厂基类引申出来的类组成工厂类列表,并通过条件判断返回符合条件的具体对象

   例子:
    1)BaseSite是基类,Tencent、Iqiyi都是继承BaseSite的类,并分别添加至工厂类
    2)SiteFactory是工厂函数类,get_site是类工厂函数,提供对工厂列表中具体类的访问方式

# coding=utf-8


class BaseSite:
    url_patterns = []

    def process(self):
        print('process common')


class Tencent(BaseSite):
    url_patterns = ['https://www.qq.com']

    def __init__(self):
        BaseSite.__init__(self)

    def process(self):
        print('process Tencent')


class Iqiyi(BaseSite):
    url_patterns = ['https://www.iqiyi.com']

    def __init__(self):
        BaseSite.__init__(self)

    def process(self):
        print('process iqiyi')


class SiteFactory:

    def __init__(self):
        self.all_sites = []
        self.init_factory()

    def add_site(self, cls):
        self.all_sites.append(cls)

    def init_factory(self):
        self.add_site(Tencent())
        self.add_site(Iqiyi())

    def get_site(self, url):
        import re
        for site in self.all_sites:
            for pattern in site.url_patterns:
                if re.search(pattern, url):
                    return site


if __name__ == '__main__':
    site_factory = SiteFactory()
    url = 'https://www.iqiyi.com/19191'
    site = site_factory.get_site(url)
    site.process()

  

 

posted @ 2020-05-17 19:41  Satansz  阅读(116)  评论(0编辑  收藏  举报