python 的动态类、动态对象类(我自己取的名)
python的奇技淫巧
来源:当前已经有多个不同的类,各个类都是同一个基类,这时候需要一个特殊的动态类,可以在已有的各种类之间进行切换
如下面举例的A、B两个类,此时需要一个动态的类,与其平级,但又可以在A、B之间来回切换
一、动态类
设计思路:动态类中,初始化的时候将另一个类的方法动态设置到该动态类中,重置的时候清楚掉这些方法,动态类就实现了
import inspect
from functools import partial
class A(object):
classParamA = 2
def __call__(self, *args, **kwargs):
print("===================A", args, kwargs)
def __init__(self):
self.paramA = 1
print("====A")
def addA(self, a, b):
print("A类的加法", a + 2 * b + self.paramA)
def minA(self, a, b):
print("A类的减法", a - 2 * b)
class B(object):
classParamB = 2
def __init__(self):
self.paramB = 1
print("====B")
def addB(self, a, b):
print("B类的加法", a + b + self.paramB)
def minB(self, a, b):
print("B类的减法", a - b)
classMap = {"A": A, "B": B}
class DynamicClass(object):
"""可以动态类"""
def __init__(self, type):
self.setClass(type)
def setClass(self, type):
self.type = type
cls = classMap[type]
for funcInfo in inspect.getmembers(cls, inspect.isfunction):
funcName = funcInfo[0]
func = funcInfo[1]
if funcName != "__init__":
setattr(self, funcName, partial(func, self))
cls.__init__(self)
def resetClass(self, type):
cls = classMap[self.type]
for funcInfo in inspect.getmembers(cls, inspect.isfunction):
funcName = funcInfo[0]
if funcName != "__init__":
delattr(self, funcName)
self.setClass(type)
a = DynamicClass("A")
a.addA(11, 11)
a.resetClass("B")
a.addB(11, 11)
运行结果如下:
二、动态对象类
为什么称之为动态对象类,因为它相当于是一个类中存有一个动态变化的对象,这个对象依据传入的类名而变动。
设计思路:
1、首先,我们知道 __ getattribute __ 方法在调用类中所有的属性时都会被调用到,并且通过该方法获得对象(python中皆为对象,包括方法也是)
2、我们在调用方法的时候,通过 __ getattribute __ 方法,获取到对象的方法并调用
# -*- coding: utf-8 -*-
import inspect
from functools import partial
class A(object):
classParamA = 2
def __call__(self, *args, **kwargs):
print("===================A", args, kwargs)
def __init__(self):
self.paramA = 1
print("====A")
def addA(self, a, b):
print("A类的加法", a + 2 * b + self.paramA)
def minA(self, a, b):
print("A类的减法", a - 2 * b)
def multi(self, a, b):
print("A类的乘法", a * b)
class B(object):
classParamB = 2
def __init__(self):
self.paramB = 1
print("====B")
def addB(self, a, b):
print("B类的加法", a + b + self.paramB)
def minB(self, a, b):
print("B类的减法", a - b)
def multi(self, a, b):
print("B类的乘法", a * b)
classMap = {"A": A, "B": B}
class DynamicClass(object):
"""可以动态类"""
def __init__(self, dynamicType):
self.obj = None
self.dynamicType = None
self.resetClass(dynamicType)
def __getattribute__(self, *args, **kwargs):
""" Return getattr(self, name). """
if args[0] not in ["resetClass", "type", "obj", "__dict__", "multi"]:
return self.obj.__getattribute__(*args, **kwargs)
return super(DynamicClass, self).__getattribute__(*args, **kwargs)
def __getattr__(self, item):
"""如果有必要,可以在这里做特殊处理"""
return self.__dict__[item]
def __setattr__(self, key, value):
"""如果有必要,可以在这里做特殊处理"""
self.__dict__[key] = value
def resetClass(self, dynamicType, *args, **kwargs):
self.dynamicType = dynamicType
cls = classMap.get(dynamicType)
if cls:
self.obj = cls(*args, **kwargs)
def multi(self, a, b):
"""要做一些骚操作"""
a = a + 1
self.obj.multi(a, b)
a = DynamicClass("A")
a.addA(11, 11)
a.minA(11, 11)
a.multi(11, 11)
a.resetClass("B")
a.addB(11, 11)
a.minB(11, 11)
a.multi(11, 11)
需要注意的点:在 __ getattribute __ 中,我们需要把动态对象类中的原有方法以及对象(就是该类中的原有属性)过滤掉,否则会因为循环调用导致python崩溃。
def __getattribute__(self, *args, **kwargs):
""" Return getattr(self, name). """
if args[0] not in ["resetClass", "type", "obj", "__dict__", "multi"]:
return self.obj.__getattribute__(*args, **kwargs)
return super(DynamicClass, self).__getattribute__(*args, **kwargs)
运行结果如下: